Re: [PATCH] Enhanced scripts/build and related Python scripts to support export files that make up an image versus uploading them to an image

2017-08-16 Thread miha . plesko . xlab

This is amazing, it seems like we were using the osv.bootstrap package of 
size 1.3 MB only because we didn't know it can be stripped. With the patch 
that Waldek provided here
we're now having osv.bootstrap package shrinked to 325 kB without any 
functionality lost. I've just integrated the patch into our 
capstan-packages platform and everything seems to
be working so far.

@Waldek could we support specifying path to the export directory via 
argument, say `scripts/build image=empty export=all 
export-dir=/path/to/my/dir`? This would be very convenient for our 
capstan-packages platform, where otherwise we need to manually
copy the content of build/export for each of the recipes to the desired 
location.

Thank you so much!




Dne sreda, 16. avgust 2017 13.52.03 UTC+2 je oseba Nadav Har'El napisala:
>
>
> On Wed, Aug 16, 2017 at 2:12 PM,  
> wrote:
>
>> Perhaps you were right anyway - we are using some patches to 
>> upload_manifest, so we might have broken the stripping. So if I understand 
>> you right, the stripped cpiod (that is as small as 220 KB) should work the 
>> same as the unstripped one, or will things crash?
>>
>
> Yes, the stripped executable should be perfectly fine and shouldn't crash. 
> The only thing you can't usefully do with it is debug with gdb. This is why 
> we use the trick of leaving the original file (cpiod.so) unstripped, and 
> stripping a copy (cpio-stripped.so) and this copy is what gets uploaded. 
>
> Nadav.
>

-- 
You received this message because you are subscribed to the Google Groups "OSv 
Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to osv-dev+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [PATCH] Enhanced scripts/build and related Python scripts to support export files that make up an image versus uploading them to an image

2017-08-16 Thread Nadav Har'El
On Wed, Aug 16, 2017 at 2:12 PM,  wrote:

> Perhaps you were right anyway - we are using some patches to
> upload_manifest, so we might have broken the stripping. So if I understand
> you right, the stripped cpiod (that is as small as 220 KB) should work the
> same as the unstripped one, or will things crash?
>

Yes, the stripped executable should be perfectly fine and shouldn't crash.
The only thing you can't usefully do with it is debug with gdb. This is why
we use the trick of leaving the original file (cpiod.so) unstripped, and
stripping a copy (cpio-stripped.so) and this copy is what gets uploaded.

Nadav.

-- 
You received this message because you are subscribed to the Google Groups "OSv 
Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to osv-dev+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [PATCH] Enhanced scripts/build and related Python scripts to support export files that make up an image versus uploading them to an image

2017-08-16 Thread miha . plesko . xlab
Perhaps you were right anyway - we are using some patches to 
upload_manifest, so we might have broken the stripping. So if I understand 
you right, the stripped cpiod (that is as small as 220 KB) should work the 
same as the unstripped one, or will things crash?

Dne sreda, 16. avgust 2017 13.01.42 UTC+2 je oseba Nadav Har'El napisala:
>
>
> On Wed, Aug 16, 2017 at 1:33 PM, Nadav Har'El  > wrote:
>
>>
>> On Wed, Aug 16, 2017 at 12:45 PM,  
>> wrote:
>>
>>>
>>> Thank you Waldek for trying to upstream this, I'm looking forward to be 
>>> removing the current patches from the capstan-packages build platform in
>>> favor of using upstreamed code! :D
>>>
>>> Unfortunately I'm not very familiar with the scripts that we're patching 
>>> here, the patches that we're currently using on capstan-packages build 
>>> platform were
>>> prepared by Gregor (I'm CC-ing him in this comment, hopefully he will be 
>>> able to review your changes). So I'll not be able to provide a helpful 
>>> review of your code -
>>> however, I'll definetly test it as a user.
>>>
>>> I've applied your patch locally and tested the `./scripts/build 
>>> image=empty export=all` command. I have two comments already:
>>>
>>> 1) I compare directory structure of current osv.bootstrap package with 
>>> that of build/export and I can see all files are identical except the 
>>> tools/cpiod.so file.
>>> In current osv.bootstrap packages size of tools/cpiod.so file is 1.8 MB, 
>>> while the cpiod.so provided by `./scripts/build image=empty export=all` is 
>>> only 220 KB.
>>> Do you perhaps have any idea what could cause the difference?
>>>
>>
>> 1.8 MB is the unstripped size, 200K is the stripped size.
>> scripts/upload_manifest.py has some logic of what to strip, and it strips 
>> stuff in modules/ and apps/ subdirectories - but forgets to strip files 
>> outside these directories, and that includes cpiod.so :-( That is a bug and 
>> should be fixed. I'll open an issue to remember I want to fix this.
>>
>
> I was wrong here - we upload_manifest.py didn't have such a bug - it also 
> stripped everything (*.so) inside the build directory, and cpiod.so was in 
> that directory, so it does get correctly stripped.
>
> Nadav.
>

-- 
You received this message because you are subscribed to the Google Groups "OSv 
Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to osv-dev+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [PATCH] Enhanced scripts/build and related Python scripts to support export files that make up an image versus uploading them to an image

2017-08-16 Thread Nadav Har'El
On Wed, Aug 16, 2017 at 1:33 PM, Nadav Har'El  wrote:

>
> On Wed, Aug 16, 2017 at 12:45 PM,  wrote:
>
>>
>> Thank you Waldek for trying to upstream this, I'm looking forward to be
>> removing the current patches from the capstan-packages build platform in
>> favor of using upstreamed code! :D
>>
>> Unfortunately I'm not very familiar with the scripts that we're patching
>> here, the patches that we're currently using on capstan-packages build
>> platform were
>> prepared by Gregor (I'm CC-ing him in this comment, hopefully he will be
>> able to review your changes). So I'll not be able to provide a helpful
>> review of your code -
>> however, I'll definetly test it as a user.
>>
>> I've applied your patch locally and tested the `./scripts/build
>> image=empty export=all` command. I have two comments already:
>>
>> 1) I compare directory structure of current osv.bootstrap package with
>> that of build/export and I can see all files are identical except the
>> tools/cpiod.so file.
>> In current osv.bootstrap packages size of tools/cpiod.so file is 1.8 MB,
>> while the cpiod.so provided by `./scripts/build image=empty export=all` is
>> only 220 KB.
>> Do you perhaps have any idea what could cause the difference?
>>
>
> 1.8 MB is the unstripped size, 200K is the stripped size.
> scripts/upload_manifest.py has some logic of what to strip, and it strips
> stuff in modules/ and apps/ subdirectories - but forgets to strip files
> outside these directories, and that includes cpiod.so :-( That is a bug and
> should be fixed. I'll open an issue to remember I want to fix this.
>

I was wrong here - we upload_manifest.py didn't have such a bug - it also
stripped everything (*.so) inside the build directory, and cpiod.so was in
that directory, so it does get correctly stripped.

Nadav.

-- 
You received this message because you are subscribed to the Google Groups "OSv 
Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to osv-dev+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [PATCH] Enhanced scripts/build and related Python scripts to support export files that make up an image versus uploading them to an image

2017-08-16 Thread Nadav Har'El
On Wed, Aug 16, 2017 at 12:45 PM,  wrote:

>
> Thank you Waldek for trying to upstream this, I'm looking forward to be
> removing the current patches from the capstan-packages build platform in
> favor of using upstreamed code! :D
>
> Unfortunately I'm not very familiar with the scripts that we're patching
> here, the patches that we're currently using on capstan-packages build
> platform were
> prepared by Gregor (I'm CC-ing him in this comment, hopefully he will be
> able to review your changes). So I'll not be able to provide a helpful
> review of your code -
> however, I'll definetly test it as a user.
>
> I've applied your patch locally and tested the `./scripts/build
> image=empty export=all` command. I have two comments already:
>
> 1) I compare directory structure of current osv.bootstrap package with
> that of build/export and I can see all files are identical except the
> tools/cpiod.so file.
> In current osv.bootstrap packages size of tools/cpiod.so file is 1.8 MB,
> while the cpiod.so provided by `./scripts/build image=empty export=all` is
> only 220 KB.
> Do you perhaps have any idea what could cause the difference?
>

1.8 MB is the unstripped size, 200K is the stripped size.
scripts/upload_manifest.py has some logic of what to strip, and it strips
stuff in modules/ and apps/ subdirectories - but forgets to strip files
outside these directories, and that includes cpiod.so :-( That is a bug and
should be fixed. I'll open an issue to remember I want to fix this.
I guess that Waldek's new export_manifest.py code strips everything *.so?


>
> 2) When running `./scripts/build image=empty export=all` I've noticed that
> not only build/export directory is filled with content, but also
> build/last/loader.img is created.
> I'm thinking if it would be possible to prevent building actual image in
> case when `export` mode is enabled - hopefully this would reduce build time.
>

But loader.img is not the full image, it's just the OSv kernel. If nothing
in OSv's source code changed, it won't be rebuilt.

But you're right, theoretically, we don't need to build the OSv kernel at
all for build export=all to work. There is just a snag that some of the
modules (even the default usr.manifest.skel) need to compile some stuff
(like cpiod.so) even if they don't need the OSv kernel.


>
> Right now I'm modifying the capstan-packages platform locally to test it
> with your patches, I'll let you know how it works. I'm looking forward to
> be hearing your opinion about the two questions above.
>
>
> Dne sreda, 09. avgust 2017 13.47.46 UTC+2 je oseba Waldek Kozaczuk
> napisala:
>>
>> This patch enhances OSv build scripts to allow exporting files in
>> addition
>> of uploading them to an image. It addresses 3 usage scenarios described
>> in
>>  #900 and demostrated by examples below:
>>
>> - ./scripts/build image=empty export=all - export files that are
>> specified is usr.manifest.skel in order to be able to produce capstan
>> osv.bootstrap package
>>
>> - ./scripts/build image=java-isolated export=all usrskel=none - export
>> files that are part of OSv modules (./modules directory) along with all
>> other dependent modules minus what is part of usr.manifest.skel
>>
>> - ./scripts/build image=openjdk8-zulu-compact1 export=selected
>> usrskel=none - export files that are part of an app (most applicable to
>> apps/openjdk8-) without any dependent modules
>>
>> The export logic is enabled by passing new parameter export
>> [=none|all|selected] to scripts/build.
>> Exported files are placed under build/export directory.
>>
>> Please note that the changes are backwards compatible. However changes to
>> scripts/upload_manifest.py
>>  will break patches that are part of https://github.com/mikelangelo
>> -project/capstan-packages/tree/master/docker_files/common. Hopefully
>> this patch will make some of these patches obsolete.
>>
>> Fixed #900
>>
>> Signed-off-by: Waldemar Kozaczuk 
>> ---
>>  modules/empty/module.py|  0
>>  scripts/build  | 16 +++-
>>  scripts/export_manifest.py | 91 
>> ++
>>
>>  scripts/manifest_common.py | 78 +++
>>  scripts/module.py  |  8 +++-
>>  scripts/upload_manifest.py | 79 +---
>>
>>  6 files changed, 192 insertions(+), 80 deletions(-)
>>  create mode 100644 modules/empty/module.py
>>  create mode 100755 scripts/export_manifest.py
>>  create mode 100644 scripts/manifest_common.py
>>
>> diff --git a/modules/empty/module.py b/modules/empty/module.py
>> new file mode 100644
>> index 000..e69de29
>> diff --git a/scripts/build b/scripts/build
>> index 7cee19c..14b4fe1 100755
>> --- a/scripts/build
>> +++ b/scripts/build
>> @@ -62,6 +62,7 @@ then
>>  exit 2
>>  fi
>>  OUT=build/`readlink build/last`
>> +EXPORT_DIR=`realpath build/export`
>>
>>  # Look for arguments that look like "name=value", and 

Re: [PATCH] Enhanced scripts/build and related Python scripts to support export files that make up an image versus uploading them to an image

2017-08-16 Thread Justin Cinkelj



On 08/15/2017 03:38 PM, Nadav Har'El wrote:


On Wed, Aug 9, 2017 at 2:47 PM, Waldemar Kozaczuk 
> wrote:


This patch enhances OSv build scripts to allow exporting files in
addition
of uploading them to an image. It addresses 3 usage scenarios
described in
 #900 and demostrated by examples below:

- ./scripts/build image=empty export=all - export files that are
specified is usr.manifest.skel in order to be able to produce
capstan osv.bootstrap package

- ./scripts/build image=java-isolated export=all usrskel=none -
export files that are part of OSv modules (./modules directory)
along with all other dependent modules minus what is part of
usr.manifest.skel

- ./scripts/build image=openjdk8-zulu-compact1 export=selected
usrskel=none - export files that are part of an app (most
applicable to apps/openjdk8-) without any dependent modules

The export logic is enabled by passing new parameter export
[=none|all|selected] to scripts/build.
Exported files are placed under build/export directory.

Please note that the changes are backwards compatible. However
changes to scripts/upload_manifest.py
 will break patches that are part of

https://github.com/mikelangelo-project/capstan-packages/tree/master/docker_files/common

.
Hopefully this patch will make some of these patches obsolete.


Justin, can you please take a look what kind of grief (or on the 
contrary?) this patch will cause you if committed?
Miha, I guess you are familiar (author?) of building capstan image in 
docker feature? Could you review the code?

Justin



Fixed #900

Signed-off-by: Waldemar Kozaczuk >
---
 modules/empty/module.py|  0
 scripts/build  | 16 +++-
 scripts/export_manifest.py | 91
++
 scripts/manifest_common.py | 78
+++
 scripts/module.py  |  8 +++-
 scripts/upload_manifest.py | 79
+---
 6 files changed, 192 insertions(+), 80 deletions(-)
 create mode 100644 modules/empty/module.py
 create mode 100755 scripts/export_manifest.py
 create mode 100644 scripts/manifest_common.py

diff --git a/modules/empty/module.py b/modules/empty/module.py
new file mode 100644
index 000..e69de29
diff --git a/scripts/build b/scripts/build
index 7cee19c..14b4fe1 100755
--- a/scripts/build
+++ b/scripts/build
@@ -62,6 +62,7 @@ then
exit 2
 fi
 OUT=build/`readlink build/last`
+EXPORT_DIR=`realpath build/export`


 # Look for arguments that look like "name=value", and set them in an
 # assoative array "vars". Also look for the "-j ..." parallelism
option,
@@ -69,6 +70,7 @@ OUT=build/`readlink build/last`
 declare -A vars
 j_arg=
 checknumber=
+vars[export]=none
 for i
 do
if test -n "$checknumber"
@@ -147,7 +149,12 @@ then
usrskel_arg="--usrskel ${vars[usrskel]}"
 fi

-jdkbase=$jdkbase ARCH=$arch mode=$mode OSV_BASE=$SRC
OSV_BUILD_PATH=$OSV_BUILD_PATH scripts/module.py $j_arg build -c
$modules $usrskel_arg

+export=${vars[export]}


Instead of setting the default "none" above, you could do this in this 
line:


export=${vars[export]-none}

I think it will be clearer (and more similar to the way we set the 
defaults for the other variables).


+if [ "$export" != "none" ]
+then
+rm -rf $EXPORT_DIR


This is really scary. What if we have a bug and $EXPORT_DIR is . or / 
or some other mistake? What if there's a space in EXPORT_DIR?


For example, consider that the current directory is "/home/nyh/osv 2" 
(with a space).

This code will run
 rm -rf /home/nyh/osv 2

So will remove the unrelated directory (!) /home/nyh/osv and also ./2, 
who knows what those might contain :-(


I suggest to just be explicit and write

rm -rf build/export

Unless I'm missing something, you don't even need the full path.

+fi
+jdkbase=$jdkbase ARCH=$arch mode=$mode OSV_BASE=$SRC
OSV_BUILD_PATH=$OSV_BUILD_PATH scripts/module.py $j_arg build -c
$modules $usrskel_arg --export $export


 bootfs_manifest=$manifest make "${args[@]}" | tee -a build.out
 # check exit status of make
@@ -180,7 +187,12 @@ zfs)
qemu-img convert -f raw -O qcow2 bare.raw usr.img
qemu-img resize usr.img ${fs_size}b >/dev/null 2>&1

-   $SRC/scripts/upload_manifest.py -o usr.img -m usr.manifest
-D jdkbase=$jdkbase -D gccbase=$gccbase -D glibcbase=$glibcbase -D
miscbase=$miscbase
+   if [ "$export" == "none" ]
+   then
+   $SRC/scripts/upload_manifest.py 

Re: [PATCH] Enhanced scripts/build and related Python scripts to support export files that make up an image versus uploading them to an image

2017-08-15 Thread Nadav Har'El
On Wed, Aug 9, 2017 at 2:47 PM, Waldemar Kozaczuk 
wrote:

> This patch enhances OSv build scripts to allow exporting files in addition
> of uploading them to an image. It addresses 3 usage scenarios described in
>  #900 and demostrated by examples below:
>
> - ./scripts/build image=empty export=all - export files that are specified
> is usr.manifest.skel in order to be able to produce capstan osv.bootstrap
> package
>
> - ./scripts/build image=java-isolated export=all usrskel=none - export
> files that are part of OSv modules (./modules directory) along with all
> other dependent modules minus what is part of usr.manifest.skel
>
> - ./scripts/build image=openjdk8-zulu-compact1 export=selected
> usrskel=none - export files that are part of an app (most applicable to
> apps/openjdk8-) without any dependent modules
>
> The export logic is enabled by passing new parameter export
> [=none|all|selected] to scripts/build.
> Exported files are placed under build/export directory.
>
> Please note that the changes are backwards compatible. However changes to
> scripts/upload_manifest.py
>  will break patches that are part of https://github.com/
> mikelangelo-project/capstan-packages/tree/master/docker_files/common.
> Hopefully this patch will make some of these patches obsolete.
>

Justin, can you please take a look what kind of grief (or on the contrary?)
this patch will cause you if committed?


>
> Fixed #900
>
> Signed-off-by: Waldemar Kozaczuk 
> ---
>  modules/empty/module.py|  0
>  scripts/build  | 16 +++-
>  scripts/export_manifest.py | 91 ++
> 
>  scripts/manifest_common.py | 78 +++
>  scripts/module.py  |  8 +++-
>  scripts/upload_manifest.py | 79 +---
>  6 files changed, 192 insertions(+), 80 deletions(-)
>  create mode 100644 modules/empty/module.py
>  create mode 100755 scripts/export_manifest.py
>  create mode 100644 scripts/manifest_common.py
>
> diff --git a/modules/empty/module.py b/modules/empty/module.py
> new file mode 100644
> index 000..e69de29
> diff --git a/scripts/build b/scripts/build
> index 7cee19c..14b4fe1 100755
> --- a/scripts/build
> +++ b/scripts/build
> @@ -62,6 +62,7 @@ then
> exit 2
>  fi
>  OUT=build/`readlink build/last`
> +EXPORT_DIR=`realpath build/export`
>

>  # Look for arguments that look like "name=value", and set them in an
>  # assoative array "vars". Also look for the "-j ..." parallelism option,
> @@ -69,6 +70,7 @@ OUT=build/`readlink build/last`
>  declare -A vars
>  j_arg=
>  checknumber=
> +vars[export]=none
>  for i
>  do
> if test -n "$checknumber"
> @@ -147,7 +149,12 @@ then
> usrskel_arg="--usrskel ${vars[usrskel]}"
>  fi
>
> -jdkbase=$jdkbase ARCH=$arch mode=$mode OSV_BASE=$SRC
> OSV_BUILD_PATH=$OSV_BUILD_PATH scripts/module.py $j_arg build -c $modules
> $usrskel_arg
>
+export=${vars[export]}
>

Instead of setting the default "none" above, you could do this in this line:

export=${vars[export]-none}

I think it will be clearer (and more similar to the way we set the defaults
for the other variables).


> +if [ "$export" != "none" ]
> +then
> +rm -rf $EXPORT_DIR
>

This is really scary. What if we have a bug and $EXPORT_DIR is . or / or
some other mistake? What if there's a space in EXPORT_DIR?

For example, consider that the current directory is "/home/nyh/osv 2" (with
a space).
This code will run
 rm -rf /home/nyh/osv 2

So will remove the unrelated directory (!) /home/nyh/osv and also ./2, who
knows what those might contain :-(

I suggest to just be explicit and write

rm -rf build/export

Unless I'm missing something, you don't even need the full path.


> +fi
> +jdkbase=$jdkbase ARCH=$arch mode=$mode OSV_BASE=$SRC
> OSV_BUILD_PATH=$OSV_BUILD_PATH scripts/module.py $j_arg build -c $modules
> $usrskel_arg --export $export
>

>  bootfs_manifest=$manifest make "${args[@]}" | tee -a build.out
>  # check exit status of make
> @@ -180,7 +187,12 @@ zfs)
> qemu-img convert -f raw -O qcow2 bare.raw usr.img
> qemu-img resize usr.img ${fs_size}b >/dev/null 2>&1
>
> -   $SRC/scripts/upload_manifest.py -o usr.img -m usr.manifest -D
> jdkbase=$jdkbase -D gccbase=$gccbase -D glibcbase=$glibcbase -D
> miscbase=$miscbase
> +   if [ "$export" == "none" ]
> +   then
> +   $SRC/scripts/upload_manifest.py -o usr.img -m
> usr.manifest -D jdkbase=$jdkbase -D gccbase=$gccbase -D
> glibcbase=$glibcbase -D miscbase=$miscbase
> +else
> +   $SRC/scripts/export_manifest.py -e $EXPORT_DIR -m
> usr.manifest -D jdkbase=$jdkbase -D gccbase=$gccbase -D
> glibcbase=$glibcbase -D miscbase=$miscbase
> +   fi
> ;;
>  ramfs)
> qemu-img convert -f raw -O qcow2 loader.img usr.img
> diff --git a/scripts/export_manifest.py b/scripts/export_manifest.py
> new file mode 100755
> index 

[PATCH] Enhanced scripts/build and related Python scripts to support export files that make up an image versus uploading them to an image

2017-08-09 Thread Waldemar Kozaczuk
This patch enhances OSv build scripts to allow exporting files in addition
of uploading them to an image. It addresses 3 usage scenarios described in
 #900 and demostrated by examples below:

- ./scripts/build image=empty export=all - export files that are specified is 
usr.manifest.skel in order to be able to produce capstan osv.bootstrap package

- ./scripts/build image=java-isolated export=all usrskel=none - export files 
that are part of OSv modules (./modules directory) along with all other 
dependent modules minus what is part of usr.manifest.skel

- ./scripts/build image=openjdk8-zulu-compact1 export=selected usrskel=none - 
export files that are part of an app (most applicable to apps/openjdk8-) 
without any dependent modules

The export logic is enabled by passing new parameter export 
[=none|all|selected] to scripts/build. 
Exported files are placed under build/export directory. 

Please note that the changes are backwards compatible. However changes to 
scripts/upload_manifest.py
 will break patches that are part of 
https://github.com/mikelangelo-project/capstan-packages/tree/master/docker_files/common.
 Hopefully this patch will make some of these patches obsolete.

Fixed #900

Signed-off-by: Waldemar Kozaczuk 
---
 modules/empty/module.py|  0
 scripts/build  | 16 +++-
 scripts/export_manifest.py | 91 ++
 scripts/manifest_common.py | 78 +++
 scripts/module.py  |  8 +++-
 scripts/upload_manifest.py | 79 +---
 6 files changed, 192 insertions(+), 80 deletions(-)
 create mode 100644 modules/empty/module.py
 create mode 100755 scripts/export_manifest.py
 create mode 100644 scripts/manifest_common.py

diff --git a/modules/empty/module.py b/modules/empty/module.py
new file mode 100644
index 000..e69de29
diff --git a/scripts/build b/scripts/build
index 7cee19c..14b4fe1 100755
--- a/scripts/build
+++ b/scripts/build
@@ -62,6 +62,7 @@ then
exit 2
 fi
 OUT=build/`readlink build/last`
+EXPORT_DIR=`realpath build/export`
 
 # Look for arguments that look like "name=value", and set them in an
 # assoative array "vars". Also look for the "-j ..." parallelism option,
@@ -69,6 +70,7 @@ OUT=build/`readlink build/last`
 declare -A vars
 j_arg=
 checknumber=
+vars[export]=none
 for i
 do
if test -n "$checknumber"
@@ -147,7 +149,12 @@ then
usrskel_arg="--usrskel ${vars[usrskel]}"
 fi
 
-jdkbase=$jdkbase ARCH=$arch mode=$mode OSV_BASE=$SRC 
OSV_BUILD_PATH=$OSV_BUILD_PATH scripts/module.py $j_arg build -c $modules 
$usrskel_arg
+export=${vars[export]}
+if [ "$export" != "none" ]
+then
+rm -rf $EXPORT_DIR
+fi
+jdkbase=$jdkbase ARCH=$arch mode=$mode OSV_BASE=$SRC 
OSV_BUILD_PATH=$OSV_BUILD_PATH scripts/module.py $j_arg build -c $modules 
$usrskel_arg --export $export
 
 bootfs_manifest=$manifest make "${args[@]}" | tee -a build.out
 # check exit status of make
@@ -180,7 +187,12 @@ zfs)
qemu-img convert -f raw -O qcow2 bare.raw usr.img
qemu-img resize usr.img ${fs_size}b >/dev/null 2>&1
 
-   $SRC/scripts/upload_manifest.py -o usr.img -m usr.manifest -D 
jdkbase=$jdkbase -D gccbase=$gccbase -D glibcbase=$glibcbase -D 
miscbase=$miscbase
+   if [ "$export" == "none" ]
+   then
+   $SRC/scripts/upload_manifest.py -o usr.img -m usr.manifest -D 
jdkbase=$jdkbase -D gccbase=$gccbase -D glibcbase=$glibcbase -D 
miscbase=$miscbase
+else
+   $SRC/scripts/export_manifest.py -e $EXPORT_DIR -m usr.manifest 
-D jdkbase=$jdkbase -D gccbase=$gccbase -D glibcbase=$glibcbase -D 
miscbase=$miscbase
+   fi
;;
 ramfs)
qemu-img convert -f raw -O qcow2 loader.img usr.img
diff --git a/scripts/export_manifest.py b/scripts/export_manifest.py
new file mode 100755
index 000..f5a957a
--- /dev/null
+++ b/scripts/export_manifest.py
@@ -0,0 +1,91 @@
+#!/usr/bin/python
+
+import optparse, os, shutil
+from manifest_common import add_var, expand, unsymlink, read_manifest, 
defines, strip_file
+
+# This will export the package based on the provided manifest file. It uses 
the same mechanism to
+# get the files that need copying as the actual upload process. The only 
current limitation is
+# support for links in OSv, e.g., /etc/mnttab: ->/proc/mounts.
+def export_package(manifest, dest):
+abs_dest = os.path.abspath(dest)
+
+files = list(expand(manifest))
+files = [(x, unsymlink(y % defines)) for (x, y) in files]
+
+# Create the base directory where we are going to put all package files.
+if not os.path.exists(abs_dest):
+os.makedirs(abs_dest)
+
+for name, hostname in files:
+name = name[1:] if name.startswith("/") else name
+name = os.path.join(abs_dest, name)
+
+if hostname.startswith("->"):
+link_source = hostname[2:]
+target_dir = os.path.dirname(name)
+
+if