trying to make standalone game w/ Lectrote

I’m trying to build a standalone game package using Lectrote; having some trouble.

Following the directions under “Packaging a bound game” at github.com/erkyrath/lectrote#readme, I’ve managed to accomplish the following:

I have a subdirectory called “adv2xburs” inside the main Lectrote directory. Inside it I have my game file (adv2xburs.gblorb), about.html, play.html, and the package.json file, which looks like this:

{
  "name": "adv2xburs",
  "productName": "The Adventures of Twice Bursitis",
  "version": "1.0.0",
  "lectroteVersion": "1.2.8",
  "lectrotePackagedGame": "adv2xburs/adv2xburs.gblorb",
  "lectroteMacAppID": "com.gentry.adv2xburs",
  "lectroteCopyright": "Written by Michael Gentry",
  "description": "An interactive inflammation",
  "lectroteExtraFiles": [
    "adv2xburs.gblorb"
  ],
  "main": "main.js",
  "scripts": {
    "start": "electron main.js",
    "preinstall": "if [ -f quixe/LICENSE ]; then echo Quixe already installed; elif [ -d .git ]; then git submodule init; git submodule update; else git clone https://github.com/erkyrath/quixe.git; fi"
  },
  "author": "Andrew Plotkin <erkyrath@eblong.com>",
  "license": "MIT",
  "dependencies": {
    "electron": "1.6.11"
  },
  "devDependencies": {
    "electron-packager": "^8.0.0",
    "appdmg": "^0.4.0"
  }
}

I open a command prompt and type:

python.exe makedist.py win32-x64 --game \adv2xburs

I then get the following output:

Lectrote version: 1.2.8
Installing to: tempapp
Traceback (most recent call last):
  File "makedist.py", line 316, in <module>
    builddir(dest, pack, pkg)
  File "makedist.py", line 245, in builddir
    subprocess.call(args)
  File "C:\Users\mikeg\AppData\Local\Programs\Python\Python36-32\lib\subprocess.py", line 267, in call
    with Popen(*popenargs, **kwargs) as p:
  File "C:\Users\mikeg\AppData\Local\Programs\Python\Python36-32\lib\subprocess.py", line 707, in __init__
    restore_signals, start_new_session)
  File "C:\Users\mikeg\AppData\Local\Programs\Python\Python36-32\lib\subprocess.py", line 992, in _execute_child
    startupinfo)
FileNotFoundError: [WinError 2] The system cannot find the file specified

It looks like there’s a missing file in my Python directory. I installed the latest version from www.python.org/download; is there a different version/distribution that I should be using?

Any help appreciated.

Did you do the “npm install” step?

I haven’t tested this on Windows at all. It might just not work.

I should try to build Secret Letter and Shadow in lectrote.

Um, well… I tried? I have node.js installed, and based on the install instructions I assume I have to have git installed as well (which I have). I typed “npm install” at the command prompt and for a minute or two it seemed to be doing something, and then it exploded in a frankly terrifying spray of error messages. Like, I’m not entirely sure now whether I’ve actually downloaded something or not?

[spoiler][code]C:\Program Files\nodejs\node_modules\npm>npm install
npm WARN deprecated node-uuid@1.4.8: Use uuid module instead
npm WARN deprecated ignore@2.2.19: several bugs fixed in v3.2.1
npm@3.10.10 C:\Program Files\nodejs\node_modules\npm
±- deep-equal@1.0.1
±- marked@0.3.6
±- marked-man@0.1.6
±- npm-registry-couchapp@2.6.13
| ±- couchapp@0.11.0
| | ±- coffee-script@1.12.7
| | ±- connect@3.6.3
| | | ±- finalhandler@1.0.4
| | | | ±- encodeurl@1.0.1
| | | | ±- escape-html@1.0.3
| | | | ±- on-finished@2.3.0
| | | | | -- ee-first@1.1.1 | | | | – statuses@1.3.1
| | | ±- parseurl@1.3.2
| | | -- utils-merge@1.0.0 | | +-- http-proxy@0.8.7 | | | +-- colors@0.6.2 | | | +-- optimist@0.3.7 | | | | – wordwrap@0.0.3
| | | -- pkginfo@0.2.3 | | +-- nano@6.4.0 | | | +-- errs@0.3.2 | | | +-- follow@0.12.1 | | | | +-- browser-request@0.3.3 | | | | – request@2.55.0
| | | | ±- aws-sign2@0.5.0
| | | | ±- bl@0.9.5
| | | | | -- readable-stream@1.0.34 | | | | | +-- isarray@0.0.1 | | | | | – string_decoder@0.10.31
| | | | ±- caseless@0.9.0
| | | | ±- combined-stream@0.0.7
| | | | | -- delayed-stream@0.0.5 | | | | +-- form-data@0.2.0 | | | | | – async@0.9.2
| | | | ±- har-validator@1.8.0
| | | | | -- bluebird@2.11.0 | | | | +-- hawk@2.3.1 | | | | +-- http-signature@0.10.1 | | | | | +-- asn1@0.1.11 | | | | | +-- assert-plus@0.1.5 | | | | | – ctype@0.5.3
| | | | ±- mime-types@2.0.14
| | | | | -- mime-db@1.12.0 | | | | +-- node-uuid@1.4.8 | | | | +-- oauth-sign@0.6.0 | | | | – qs@2.4.2
| | | ±- request@2.81.0
| | | | ±- aws-sign2@0.6.0
| | | | ±- caseless@0.12.0
| | | | ±- combined-stream@1.0.5
| | | | | -- delayed-stream@1.0.0 | | | | +-- form-data@2.1.4 | | | | +-- har-validator@4.2.1 | | | | | – har-schema@1.0.5
| | | | ±- hawk@3.1.3
| | | | ±- http-signature@1.1.1
| | | | | -- assert-plus@0.2.0 | | | | +-- mime-types@2.1.17 | | | | | – mime-db@1.30.0
| | | | ±- oauth-sign@0.8.2
| | | | ±- performance-now@0.2.0
| | | | ±- qs@6.4.0
| | | | ±- safe-buffer@5.1.1
| | | | ±- tunnel-agent@0.6.0
| | | | -- uuid@3.1.0 | | | – underscore@1.8.3
| | ±- url@0.11.0
| | | ±- punycode@1.3.2
| | | -- querystring@0.2.0 | | – watch@0.8.0
| ±- json@9.0.6
| -- semver@4.3.6 +-- npm-registry-mock@1.0.1 | +-- hock@0.2.5 | | – deep-equal@0.2.1
| -- util-extend@1.0.3 +-- require-inject@1.4.2 | – caller@1.0.1
±- sprintf-js@1.0.3
±- standard@6.0.8
| ±- eslint@2.2.0
| | ±- chalk@1.1.3
| | | ±- ansi-styles@2.2.1
| | | ±- has-ansi@2.0.0
| | | -- supports-color@2.0.0 | | +-- concat-stream@1.6.0 | | | +-- readable-stream@2.3.3 | | | | +-- core-util-is@1.0.2 | | | | +-- isarray@1.0.0 | | | | +-- process-nextick-args@1.0.7 | | | | +-- string_decoder@1.0.3 | | | | – util-deprecate@1.0.2
| | | -- typedarray@0.0.6 | | +-- debug@2.6.8 | | | – ms@2.0.0
| | ±- doctrine@1.5.0
| | | -- isarray@1.0.0 | | +-- es6-map@0.1.5 | | | +-- d@1.0.0 | | | +-- es5-ext@0.10.30 | | | +-- es6-iterator@2.0.1 | | | +-- es6-set@0.1.5 | | | +-- es6-symbol@3.1.1 | | | – event-emitter@0.3.5
| | ±- escope@3.6.0
| | | ±- es6-weak-map@2.0.2
| | | -- esrecurse@4.2.0 | | +-- espree@3.5.0 | | | +-- acorn@5.1.2 | | | – acorn-jsx@3.0.1
| | | -- acorn@3.3.0 | | +-- estraverse@4.2.0 | | +-- estraverse-fb@1.3.2 | | +-- esutils@2.0.2 | | +-- file-entry-cache@1.3.1 | | | +-- flat-cache@1.2.2 | | | | +-- circular-json@0.3.3 | | | | +-- del@2.2.2 | | | | | +-- globby@5.0.0 | | | | | | +-- array-union@1.0.2 | | | | | | | – array-uniq@1.0.3
| | | | | | -- arrify@1.0.1 | | | | | +-- is-path-cwd@1.0.0 | | | | | +-- is-path-in-cwd@1.0.0 | | | | | | – is-path-inside@1.0.0
| | | | | -- pify@2.3.0 | | | | – write@0.2.1
| | | -- object-assign@4.1.1 | | +-- glob@6.0.4 | | | – minimatch@3.0.4
| | | -- brace-expansion@1.1.8 | | | +-- balanced-match@1.0.0 | | | – concat-map@0.0.1
| | ±- globals@8.18.0
| | ±- ignore@2.2.19
| | ±- inquirer@0.12.0
| | | ±- ansi-escapes@1.4.0
| | | ±- cli-cursor@1.0.2
| | | | -- restore-cursor@1.0.1 | | | | +-- exit-hook@1.1.1 | | | | – onetime@1.1.0
| | | ±- cli-width@2.2.0
| | | ±- figures@1.7.0
| | | ±- readline2@1.0.1
| | | | -- mute-stream@0.0.5 | | | +-- run-async@0.1.0 | | | +-- rx-lite@3.1.2 | | | – through@2.3.8
| | ±- is-my-json-valid@2.16.1
| | | ±- generate-function@2.0.0
| | | ±- generate-object-property@1.2.0
| | | | -- is-property@1.0.2 | | | – jsonpointer@4.0.1
| | ±- is-resolvable@1.0.0
| | | -- tryit@1.0.3 | | +-- json-stable-stringify@1.0.1 | | | – jsonify@0.0.0
| | ±- lodash@4.17.4
| | ±- optionator@0.8.2
| | | ±- deep-is@0.1.3
| | | ±- fast-levenshtein@2.0.6
| | | ±- levn@0.3.0
| | | ±- prelude-ls@1.1.2
| | | ±- type-check@0.3.2
| | | -- wordwrap@1.0.0 | | +-- path-is-absolute@1.0.1 | | +-- pluralize@1.2.1 | | +-- progress@1.1.8 | | +-- require-uncached@1.0.3 | | | +-- caller-path@0.1.0 | | | | – callsites@0.2.0
| | | -- resolve-from@1.0.1 | | +-- resolve@1.4.0 | | | – path-parse@1.0.5
| | ±- shelljs@0.5.3
| | ±- strip-json-comments@1.0.4
| | ±- table@3.8.3
| | | ±- ajv@4.11.8
| | | | -- co@4.6.0 | | | +-- ajv-keywords@1.5.1 | | | +-- slice-ansi@0.0.4 | | | – string-width@2.1.1
| | | ±- is-fullwidth-code-point@2.0.0
| | | -- strip-ansi@4.0.0 | | | – ansi-regex@3.0.0
| | -- user-home@2.0.0 | | – os-homedir@1.0.2
| ±- eslint-config-standard@5.1.0
| ±- eslint-config-standard-jsx@1.1.1
| ±- eslint-plugin-promise@1.3.2
| ±- eslint-plugin-react@4.3.0
| ±- eslint-plugin-standard@1.3.3
| ±- standard-engine@3.3.1
| | ±- defaults@1.0.3
| | | -- clone@1.0.2 | | +-- deglob@1.1.2 | | | +-- ignore@3.3.5 | | | +-- run-parallel@1.1.6 | | | – uniq@1.0.1
| | ±- find-root@1.1.0
| | ±- get-stdin@5.0.1
| | ±- minimist@1.2.0
| | ±- multiline@1.0.2
| | | -- strip-indent@1.0.1 | | | – get-stdin@4.0.1
| | -- pkg-config@1.1.1 | | – debug-log@1.0.1
| -- xtend@4.0.1 +-- tacks@1.2.6 | – yargs@3.32.0
| ±- camelcase@2.1.1
| ±- cliui@3.2.0
| | -- wrap-ansi@2.1.0 | +-- decamelize@1.2.0 | +-- os-locale@1.4.0 | | – lcid@1.0.0
| | -- invert-kv@1.0.0 | +-- string-width@1.0.2 | | +-- code-point-at@1.1.0 | | – is-fullwidth-code-point@1.0.0
| | -- number-is-nan@1.0.1 | +-- window-size@0.1.4 | – y18n@3.2.1
-- tap@7.1.2 +-- bluebird@3.5.0 +-- clean-yaml-object@0.1.0 +-- color-support@1.1.3 +-- coveralls@2.13.1 | +-- js-yaml@3.6.1 | | – esprima@2.7.3
| ±- lcov-parse@0.0.10
| ±- log-driver@1.2.5
| -- request@2.79.0 | +-- aws-sign2@0.6.0 | +-- aws4@1.6.0 | +-- caseless@0.11.0 | +-- combined-stream@1.0.5 | | – delayed-stream@1.0.0
| ±- extend@3.0.1
| ±- forever-agent@0.6.1
| ±- form-data@2.1.4
| | -- asynckit@0.4.0 | +-- har-validator@2.0.6 | | +-- commander@2.11.0 | | – pinkie-promise@2.0.1
| | -- pinkie@2.0.4 | +-- hawk@3.1.3 | | +-- boom@2.10.1 | | +-- cryptiles@2.0.5 | | +-- hoek@2.16.3 | | – sntp@1.0.9
| ±- http-signature@1.1.1
| | ±- assert-plus@0.2.0
| | ±- jsprim@1.4.1
| | | ±- assert-plus@1.0.0
| | | ±- extsprintf@1.3.0
| | | ±- json-schema@0.2.3
| | | -- verror@1.10.0 | | | – assert-plus@1.0.0
| | -- sshpk@1.13.1 | | +-- asn1@0.2.3 | | +-- assert-plus@1.0.0 | | +-- bcrypt-pbkdf@1.0.1 | | +-- dashdash@1.14.1 | | | – assert-plus@1.0.0
| | ±- ecc-jsbn@0.1.1
| | ±- getpass@0.1.7
| | | -- assert-plus@1.0.0 | | +-- jsbn@0.1.1 | | – tweetnacl@0.14.5
| ±- is-typedarray@1.0.0
| ±- isstream@0.1.2
| ±- json-stringify-safe@5.0.1
| ±- mime-types@2.1.17
| | -- mime-db@1.30.0 | +-- oauth-sign@0.8.2 | +-- qs@6.3.2 | +-- stringstream@0.0.5 | +-- tough-cookie@2.3.2 | +-- tunnel-agent@0.4.3 | – uuid@3.1.0
±- deeper@2.1.0
±- foreground-child@1.5.6
| -- cross-spawn@4.0.2 | – lru-cache@4.1.1
| ±- pseudomap@1.0.2
| -- yallist@2.1.2 +-- isexe@1.1.2 +-- js-yaml@3.10.0 | +-- argparse@1.0.9 | – esprima@4.0.0
±- nyc@7.1.0
| ±- arrify@1.0.1
| ±- caching-transform@1.0.1
| | -- write-file-atomic@1.1.4 | | +-- graceful-fs@4.1.4 | | +-- imurmurhash@0.1.4 | | – slide@1.1.6
| ±- convert-source-map@1.3.0
| ±- default-require-extensions@1.0.0
| | -- strip-bom@2.0.0 | | – is-utf8@0.2.1
| ±- find-cache-dir@0.1.1
| | ±- commondir@1.0.1
| | -- pkg-dir@1.0.0 | +-- find-up@1.1.2 | | +-- path-exists@2.1.0 | | – pinkie-promise@2.0.1
| | -- pinkie@2.0.4 | +-- foreground-child@1.5.3 | | – cross-spawn@4.0.0
| | -- lru-cache@4.0.1 | | +-- pseudomap@1.0.2 | | – yallist@2.0.0
| ±- glob@7.0.5
| | ±- fs.realpath@1.0.0
| | ±- inflight@1.0.5
| | | -- wrappy@1.0.2 | | +-- inherits@2.0.1 | | +-- minimatch@3.0.2 | | | – brace-expansion@1.1.6
| | | ±- balanced-match@0.4.2
| | | -- concat-map@0.0.1 | | +-- once@1.3.3 | | – path-is-absolute@1.0.0
| ±- istanbul-lib-coverage@1.0.0-alpha.4
| ±- istanbul-lib-hook@1.0.0-alpha.4
| | -- append-transform@0.3.0 | +-- istanbul-lib-instrument@1.1.0-alpha.4 | | +-- babel-generator@6.11.4 | | | +-- babel-messages@6.8.0 | | | +-- babel-runtime@6.9.2 | | | | +-- core-js@2.4.1 | | | | – regenerator-runtime@0.9.5
| | | ±- detect-indent@3.0.1
| | | | ±- get-stdin@4.0.1
| | | | ±- minimist@1.2.0
| | | | -- repeating@1.1.3 | | | | – is-finite@1.0.1
| | | -- lodash@4.13.1 | | +-- babel-template@6.9.0 | | +-- babel-traverse@6.11.4 | | | +-- babel-code-frame@6.11.0 | | | | +-- chalk@1.1.3 | | | | | +-- ansi-styles@2.2.1 | | | | | +-- escape-string-regexp@1.0.5 | | | | | +-- has-ansi@2.0.0 | | | | | – supports-color@2.0.0
| | | | -- js-tokens@2.0.0 | | | +-- debug@2.2.0 | | | | – ms@0.7.1
| | | ±- globals@8.18.0
| | | -- invariant@2.2.1 | | | – loose-envify@1.2.0
| | | -- js-tokens@1.0.3 | | +-- babel-types@6.11.1 | | | +-- esutils@2.0.2 | | | – to-fast-properties@1.0.2
| | -- babylon@6.8.4 | +-- istanbul-lib-report@1.0.0-alpha.3 | | +-- async@1.5.2 | | +-- path-parse@1.0.5 | | – supports-color@3.1.2
| | -- has-flag@1.0.0 | +-- istanbul-lib-source-maps@1.0.0-alpha.10 | | – source-map@0.5.6
| ±- istanbul-reports@1.0.0-alpha.8
| | -- handlebars@4.0.5 | | +-- optimist@0.6.1 | | | – wordwrap@0.0.3
| | ±- source-map@0.4.4
| | | -- amdefine@1.0.0 | | – uglify-js@2.7.0
| | ±- async@0.2.10
| | ±- uglify-to-browserify@1.0.2
| | -- yargs@3.10.0 | | +-- camelcase@1.2.1 | | +-- cliui@2.1.0 | | | +-- center-align@0.1.3 | | | | +-- align-text@0.1.4 | | | | | – longest@1.0.1
| | | | -- lazy-cache@1.0.4 | | | +-- right-align@0.1.3 | | | – wordwrap@0.0.2
| | -- window-size@0.1.0 | +-- md5-hex@1.3.0 | | – md5-o-matic@0.1.1
| ±- micromatch@2.3.11
| | ±- arr-diff@2.0.0
| | | -- arr-flatten@1.0.1 | | +-- array-unique@0.2.1 | | +-- braces@1.8.5 | | | +-- expand-range@1.8.2 | | | | – fill-range@2.2.3
| | | | ±- is-number@2.1.0
| | | | ±- isobject@2.1.0
| | | | | -- isarray@1.0.0 | | | | +-- randomatic@1.1.5 | | | | – repeat-string@1.5.4
| | | ±- preserve@0.2.0
| | | -- repeat-element@1.1.2 | | +-- expand-brackets@0.1.5 | | | – is-posix-bracket@0.1.1
| | ±- extglob@0.3.2
| | ±- filename-regex@2.0.0
| | ±- is-extglob@1.0.0
| | ±- is-glob@2.0.1
| | ±- kind-of@3.0.3
| | | -- is-buffer@1.1.3 | | +-- normalize-path@2.0.1 | | +-- object.omit@2.0.0 | | | +-- for-own@0.1.4 | | | | – for-in@0.1.5
| | | -- is-extendable@0.1.1 | | +-- parse-glob@3.0.4 | | | +-- glob-base@0.3.0 | | | | – glob-parent@2.0.0
| | | -- is-dotfile@1.0.2 | | – regex-cache@0.4.3
| | ±- is-equal-shallow@0.1.3
| | -- is-primitive@2.0.0 | +-- mkdirp@0.5.1 | | – minimist@0.0.8
| ±- pkg-up@1.0.0
| ±- resolve-from@2.0.0
| ±- rimraf@2.5.4
| ±- signal-exit@3.0.0
| ±- spawn-wrap@1.2.4
| | ±- os-homedir@1.0.1
| | ±- signal-exit@2.1.2
| | -- which@1.2.10 | | – isexe@1.1.2
| ±- test-exclude@1.1.0
| | ±- lodash.assign@4.0.9
| | | ±- lodash.keys@4.0.7
| | | -- lodash.rest@4.0.3 | | +-- read-pkg-up@1.0.1 | | | – read-pkg@1.1.0
| | | ±- load-json-file@1.1.0
| | | | ±- parse-json@2.2.0
| | | | | -- error-ex@1.3.0 | | | | | – is-arrayish@0.2.1
| | | | -- pify@2.3.0 | | | +-- normalize-package-data@2.3.5 | | | | +-- hosted-git-info@2.1.5 | | | | +-- is-builtin-module@1.0.0 | | | | | – builtin-modules@1.1.1
| | | | ±- semver@5.3.0
| | | | -- validate-npm-package-license@3.0.1 | | | | +-- spdx-correct@1.0.2 | | | | | – spdx-license-ids@1.2.1
| | | | -- spdx-expression-parse@1.0.2 | | | | – spdx-exceptions@1.0.5
| | | -- path-type@1.1.0 | | – require-main-filename@1.0.1
| ±- yargs@4.8.1
| | ±- cliui@3.2.0
| | | -- wrap-ansi@2.0.0 | | +-- decamelize@1.2.0 | | +-- get-caller-file@1.0.1 | | +-- os-locale@1.4.0 | | | – lcid@1.0.0
| | | -- invert-kv@1.0.0 | | +-- require-directory@2.1.1 | | +-- set-blocking@2.0.0 | | +-- string-width@1.0.1 | | | +-- code-point-at@1.0.0 | | | | – number-is-nan@1.0.0
| | | ±- is-fullwidth-code-point@1.0.0
| | | -- strip-ansi@3.0.1 | | | – ansi-regex@2.0.0
| | ±- which-module@1.0.0
| | ±- window-size@0.2.0
| | -- y18n@3.2.1 | – yargs-parser@2.4.1
| -- camelcase@3.0.0 +-- only-shallow@1.2.0 +-- os-homedir@1.0.1 +-- signal-exit@3.0.2 +-- stack-utils@0.4.0 +-- tap-mocha-reporter@2.0.1 | +-- diff@1.4.0 | +-- escape-string-regexp@1.0.5 | – unicode-length@1.0.3
| -- punycode@1.4.1 +-- tap-parser@2.2.3 | – events-to-array@1.1.2
`-- tmatch@2.0.1

npm ERR! Windows_NT 10.0.15063
npm ERR! argv “C:\Program Files\nodejs\node.exe” “C:\Program Files\nodejs\node_modules\npm\bin\npm-cli.js” “install”
npm ERR! node v6.11.3
npm ERR! npm v3.10.10
npm ERR! path C:\Program Files\nodejs\node_modules\npm\node_modules.staging
npm ERR! code EPERM
npm ERR! errno -4048
npm ERR! syscall mkdir

npm ERR! Error: EPERM: operation not permitted, mkdir ‘C:\Program Files\nodejs\node_modules\npm\node_modules.staging’
npm ERR! at Error (native)
npm ERR! { Error: EPERM: operation not permitted, mkdir ‘C:\Program Files\nodejs\node_modules\npm\node_modules.staging’
npm ERR! at Error (native)
npm ERR! errno: -4048,
npm ERR! code: ‘EPERM’,
npm ERR! syscall: ‘mkdir’,
npm ERR! path: ‘C:\Program Files\nodejs\node_modules\npm\node_modules\.staging’ }
npm ERR!
npm ERR! Please try running this command again as root/Administrator.
npm ERR! Windows_NT 10.0.15063
npm ERR! argv “C:\Program Files\nodejs\node.exe” “C:\Program Files\nodejs\node_modules\npm\bin\npm-cli.js” “install”
npm ERR! node v6.11.3
npm ERR! npm v3.10.10
npm ERR! path C:\Program Files\nodejs\node_modules\npm\npm-debug.log.1300302194
npm ERR! code EPERM
npm ERR! errno -4048
npm ERR! syscall open

npm ERR! Error: EPERM: operation not permitted, open ‘C:\Program Files\nodejs\node_modules\npm\npm-debug.log.1300302194’
npm ERR! at Error (native)
npm ERR! { Error: EPERM: operation not permitted, open ‘C:\Program Files\nodejs\node_modules\npm\npm-debug.log.1300302194’
npm ERR! at Error (native)
npm ERR! errno: -4048,
npm ERR! code: ‘EPERM’,
npm ERR! syscall: ‘open’,
npm ERR! path: ‘C:\Program Files\nodejs\node_modules\npm\npm-debug.log.1300302194’ }
npm ERR!
npm ERR! Please try running this command again as root/Administrator.

npm ERR! Please include the following file with any support request:
npm ERR! C:\Program Files\nodejs\node_modules\npm\npm-debug.log[/code][/spoiler]

I do have a working version of Lectrote running on my computer; the Windows package at github.com/erkyrath/lectrote/releases works just fine as an interpreter. But it doesn’t contain makedist.py or any of the other files required to package a game.

I swear I’m not completely hopeless; I can learn programming languages relatively easily, but I don’t have much experience with these kinds of developer environments. I know how the Windows command prompt works and I understand the basic concepts at work here. But I’m a bit like Peter Venkman: you have to for a moment pretend I don’t know anything about metallurgy.

Well, I may have made some progress – I managed to run the command prompt as root admin, and I did figure out that I should be running “npm install” from within the lectrote directory, at least. Here’s the output I got:

[spoiler][code]C:\Users\mikeg\Desktop\lectrote-lectrote-1.2.8>npm install

lectrote@1.2.8 preinstall C:\Users\mikeg\Desktop\lectrote-lectrote-1.2.8
if [ -f quixe/LICENSE ]; then echo Quixe already installed; elif [ -d .git ]; then git submodule init; git submodule update; else git clone GitHub - erkyrath/quixe: A Glulx VM interpreter written in Javascript; fi

-f was unexpected at this time.

npm WARN optional SKIPPING OPTIONAL DEPENDENCY: appdmg@^0.4.0 (node_modules\appdmg):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for appdmg@0.4.5: wanted {“os”:“darwin”,“arch”:“any”} (current: {“os”:“win32”,“arch”:“x64”})
npm ERR! Windows_NT 10.0.15063
npm ERR! argv “C:\Program Files\nodejs\node.exe” “C:\Program Files\nodejs\node_modules\npm\bin\npm-cli.js” “install”
npm ERR! node v6.11.3
npm ERR! npm v3.10.10
npm ERR! code ELIFECYCLE
npm ERR! lectrote@1.2.8 preinstall: if [ -f quixe/LICENSE ]; then echo Quixe already installed; elif [ -d .git ]; then git submodule init; git submodule update; else git clone https://github.com/erkyrath/quixe.git; fi
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the lectrote@1.2.8 preinstall script ‘if [ -f quixe/LICENSE ]; then echo Quixe already installed; elif [ -d .git ]; then git submodule init; git submodule update; else git clone GitHub - erkyrath/quixe: A Glulx VM interpreter written in Javascript; fi’.
npm ERR! Make sure you have the latest version of node.js and npm installed.
npm ERR! If you do, this is most likely a problem with the lectrote package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR! if [ -f quixe/LICENSE ]; then echo Quixe already installed; elif [ -d .git ]; then git submodule init; git submodule update; else git clone GitHub - erkyrath/quixe: A Glulx VM interpreter written in Javascript; fi
npm ERR! You can get information on how to open an issue for this project with:
npm ERR! npm bugs lectrote
npm ERR! Or if that isn’t available, you can get their info via:
npm ERR! npm owner ls lectrote
npm ERR! There is likely additional logging output above.
npm WARN Local package.json exists, but node_modules missing, did you mean to install?

npm ERR! Please include the following file with any support request:
npm ERR! C:\Users\mikeg\Desktop\lectrote-lectrote-1.2.8\npm-debug.log[/code][/spoiler]

Debug log is attached.
npm-debug.log (1.1 MB)

UPDATE: I managed to successfully compile Lectrote from the source code using “npm install” from the command line.

However, I still cannot package a game. I keep getting the same error (this was from attempting to package samplegame):

C:\Users\mikeg\Desktop\lectrote-lectrote-1.2.8>python.exe makedist.py --game c:\users\mikeg\desktop\lectrote-lectrote-1.2.8\samplegame Adventure version: 1.0.0 Lectrote version: 1.2.8 Installing to: tempapp Traceback (most recent call last): File "makedist.py", line 316, in <module> builddir(dest, pack, pkg) File "makedist.py", line 245, in builddir subprocess.call(args) File "C:\Users\mikeg\AppData\Local\Programs\Python\Python36-32\lib\subprocess.py", line 267, in call with Popen(*popenargs, **kwargs) as p: File "C:\Users\mikeg\AppData\Local\Programs\Python\Python36-32\lib\subprocess.py", line 707, in __init__ restore_signals, start_new_session) File "C:\Users\mikeg\AppData\Local\Programs\Python\Python36-32\lib\subprocess.py", line 992, in _execute_child startupinfo) FileNotFoundError: [WinError 2] The system cannot find the file specified

And I’m stuck. I just don’t know enough about python to work out what’s going wrong.

It’s trying to run the NPM electron-packager tool, which should have been installed by “npm install” (in the node_modules subdirectory).

But Windows just has some different layout that I don’t get. Or maybe it’s a forward-slash / backward-slash compatibility problem.

Sorry this is such a drag.

Hmm. Is the node_modules subdirectory supposed to be in the lectrote directory, or in the node.js directory, or in the python/lib directory?

I think I assumed the lectrote directory, but I may have misinterpreted.

In the lectrote directory.

Mike - if you want to do a skype or similar web screen sharing, I can probably get you through this…

I’ve been working through this…my notes:

The packages.json preinstall script is for BASH. There’s an npm library called run-script-os that allows you to define platform specific scripts (preinstall:win32). This statement has to be written for CMD on Windows.

"scripts": { "start": "electron .", "preinstall": "run-script-os", "preinstall:macos": "if [ -f quixe/LICENSE ]; then echo Quixe already installed; elif [ -d .git ]; then git submodule init; git submodule update; else git clone https://github.com/erkyrath/quixe.git; fi", "preinstall:darwin": "if [ -f quixe/LICENSE ]; then echo Quixe already installed; elif [ -d .git ]; then git submodule init; git submodule update; else git clone https://github.com/erkyrath/quixe.git; fi", "preinstall:win32": "if EXISTS quixe/LICENSE ( echo Quixe already installed) else (if EXISTS .git ( git submodule init; git submodule update; ) else (git clone https://github.com/erkyrath/quixe.git; fi)" },

This allows npm install to run correctly on windows.

Even so, the makedist.py is clearly meant for a BASH/mac environment as well and so far I can’t get it to run on Windows. I’ve inched closed, but this seems sort of counter-productive since electron has excellent multi-platform build capabilities. (zarf has mentioned he “should” port this to JS, but I assume this is not a priority)

I’m going to dig into this some more and try to get the build working without python.

I assume this works on linux and macos and won’t look at those targets.

Yeah, I was able to get npm install to work, eventually, by dropping in the quixe files manually and removing the “if [ -f quixe/LICENSE ];” from the preinstall script (this was craiglocke’s solution in this thread.

It’s makedist.py that’s giving me the problems now.

Closer. I have dist\win32-* folders created with results. Zip process is last step.

I added bestzip and updated win32 rmdir instead of rm.

Now using “makedist.py --game shadow” and realizing --game is never even checked in the program. Adding more platformy things…

More work on --game gamedir completed. I have it building into gamedir and copying to dist\gamedir-win32-x64, but the extra files aren’t getting copied and not sure yet how to make it default to built-in game.

pycharm is the bomb (JetBrains python IDE with debugger)

I’m pretty close to getting makedist.py work for win32. Of course once I do this, I’ll probably just turn this into a gulp task.

But I need a break. Stupid Brewers blew second game in a row…sheesh

Hey Zarf,

Maybe you can clarify the folder structure for me…

Assume my gamedir is ‘shadow’

I have

shadow\files\shadow-2.1.ulx
shadow\files\shadowhints.html
shadow\files\GameFiles\checkmark.png
shadow\files\GameFiles\gearclock.jpg
shadow\files\GameFiles\parchment.jpg
shadow\files\GameFiles\question.jpg

This should get copied to:

lectrote\dist\shadow-win32-x64\resources\app\shadow\files\

Right?

Am I allowed to have a sub-folder in the gamedir?

Or should I flatten all of it into the gamedir?

I’m going to conclude that “wrapped” and “unwrapped” are how the zip file is created. “unwrapped” means the zip root is the contents of the dist\win32-ia32 and doesn’t actually have the “dist\win32-ia32” as folders within the zip.

So I have makefile.py working now for a windows build. Most of the problems were the shell commands that assumed bash was in use instead of cmd on Windows. Then the assumption that a ‘zip’ command was built-in, though that was an easy fix. Then the copyfile python command on Windows won’t overwrite a file and will actually cause an error. Then the build stuff was just weird on Windows. Does like cd %s in subprocess. I had to use os.chdir() and do it once for ‘dist’ and once for gamedir. Then unwind that with ‘…\’ twice. Cra-a-azy.

I have Shadow in the Cathedral built, with hints.

If I have time in the near future, all of this really should be moved to gulp tasks. Shouldn’t be too hard and the cross-platform stuff would be much cleaner.

That is great news! Is it only a matter of replacing makedist.py with your version, or are there other changes that must be made?

That’s it, as long as you’ve removed that preinstall line in package.json.

  • Make sure you have your own folder for your story with everything it needs (under the lectrote folder, so lectrote\shadow is what I have)
  • Copy the samplegame files to your folder and make changes accordingly (minor HTML edits).
  • Update the package.json per lectrote docs (mine is shown below for shadow)
  • Make sure you list all extra files (including game file) in lectroteExtraFiles [“file1”,“file2”]
  • npm install --save-dev bestzip
  • npm install --save-dev run-script-os (if you decide to use the preinstall scripts)

build first with
py makedist.py win32

then package
py makedist.py --game yourfoldername win32

This will leave zip files in the dist folder, though you can test it by running the compiled elextron app named yourfoldername.exe in the unzipped folder.

Let me know how it goes…everything is below…

  "scripts": {
    "start": "electron .",
    "preinstall": "run-script-os",
    "preinstall:macos": "if [ -f quixe/LICENSE ]; then echo Quixe already installed; elif [ -d .git ]; then git submodule init; git submodule update; else git clone https://github.com/erkyrath/quixe.git; fi",
    "preinstall:linux": "if [ -f quixe/LICENSE ]; then echo Quixe already installed; elif [ -d .git ]; then git submodule init; git submodule update; else git clone https://github.com/erkyrath/quixe.git; fi",
    "preinstall:win32": "if EXISTS quixe/LICENSE ( echo Quixe already installed) else (if EXISTS .git ( git submodule init; git submodule update; ) else (git clone https://github.com/erkyrath/quixe.git; fi)"
  },

shadow package.json

{
  "name": "shadow",
  "productName": "shadow",
  "version": "2.1.0",
  "lectroteVersion": "2.8.1",
  "description": "The Shadow in the Cathedral",
  "author": "Ian Finely, Jon Ingold",
  "lectrotePackagedGame": "shadow-2.1.ulx",
  "lectroteSoleInterpreter": "glulx",
  "lectroteExtraFiles": ["shadow-2.1.ulx", "shadowhints.html", "checkmark.png", "gearclock.jpg", "parchment.jpg", "question.jpg",
                          "chapter-1.png", "chapter-2.png", "chapter-3.png", "chapter-4.png", "chapter-5.png", "chapter-6.png",
                          "chapter-7.png", "chapter-8.png", "chapter-9.png", "chapter-10.png", "chapter-11.png" ],
  "lectroteCopyright": "Copyright 2017 by Ian Finley & Jon Ingold",
  "main": "main.js",
  "bin": {
    "lectrote": "./cli.sh"
  },
  "scripts": {
    "start": "electron .",
    "preinstall": "run-script-os",
    "preinstall:macos": "if [ -f quixe/LICENSE ]; then echo Quixe already installed; elif [ -d .git ]; then git submodule init; git submodule update; else git clone https://github.com/erkyrath/quixe.git; fi",
    "preinstall:linux": "if [ -f quixe/LICENSE ]; then echo Quixe already installed; elif [ -d .git ]; then git submodule init; git submodule update; else git clone https://github.com/erkyrath/quixe.git; fi",
    "preinstall:win32": "if EXISTS quixe/LICENSE ( echo Quixe already installed) else (if EXISTS .git ( git submodule init; git submodule update; ) else (git clone https://github.com/erkyrath/quixe.git; fi)"
  },
  "repository": {
    "type": "git",
    "url": "https://github.com/erkyrath/lectrote.git"
  },
  "keywords": [
    "interactive fiction",
    "interpreter",
    "quixe",
    "glkote",
    "glulx",
    "parchment",
    "zcode",
    "zmachine",
    "ink"
  ],
  "license": "MIT",
  "dependencies": {
    "electron": "1.6.11"
  },
  "devDependencies": {
    "electron-packager": "^8.0.0",
    "run-script-os": "^1.0.2"
  },
  "optionalDependencies": {
    "appdmg": "^0.4.0"
  }
}

makedist.py

#!/usr/bin/env python3

# Usage: python3 makedist.py OR for Windows: py makedist.py [--game yourdir] [win32]
#
# This script copies the working files (everything needed to run Lectrote)
# into prebuilt Electron app packages. Fetch these from
#    https://github.com/atom/electron/releases
# and unzip them into a "dist" directory.

import sys
import os, os.path
import optparse
import shutil
import json
import subprocess

all_packages = [
    'darwin-x64',
    'linux-ia32',
    'linux-x64',
    'win32-ia32',
    'win32-x64',
]

popt = optparse.OptionParser()

popt.add_option('-b', '--build',
                action='store_true', dest='makedist',
                help='build dist directories')
popt.add_option('-z', '--zip',
                action='store_true', dest='makezip',
                help='turn dist directories into zip files')
popt.add_option('-n', '--none',
                action='store_true', dest='makenothing',
                help='do nothing except look at the arguments')
popt.add_option('-g', '--game', '--gamedir',
                action='store', dest='gamedir',
                help='directory for game-specific files')
popt.add_option('-v', '--version',
                action='store', dest='buildversion',
                default='1',
                help='build version (default 1)')

(opts, args) = popt.parse_args()


appfiles = [
    './package.json',
    './main.js',
    './apphooks.js',
    './formats.js',
    './play.html',
    './prefs.html',
    './prefs.js',
    './fonts.js',
    './about.html',
    './if-card.html',
    './if-card.js',
    './fonts.css',
    './play.css',
    './el-glkote.css',
    './font',  # all files
    './icon-128.png',
    './docicon-glulx.ico',
    './docicon-zcode.ico',
    './docicon-hugo.ico',
    './docicon-json.ico',
    './quixe/lib/elkote.min.js',
    './quixe/lib/jquery-1.12.4.min.js',
    './quixe/lib/quixe.min.js',
    './quixe/media/waiting.gif',
    {
        'key': 'ifvms',
        'files': [
            './zplay.html',
            './ifvms/zvm.min.js',
            './ifvms/zvm_dispload.min.js',
            './ifvms/zvm.css',
            './ifvms/package.json',
        ]
    },
    {
        'key': 'emglken',
        'files': [
            './emglkenplay.html',
            './emglken/hugo.js',
            './emglken/hugo-core.js.bin',
            './emglken/hugo-core.js.mem',
            './emglken/git.js',
            './emglken/git-core.js.bin',
            './emglken/git-core.js.mem',
            './emglken/emglken_dispload.min.js',
            './emglken/versions.json',
        ]
    },
    {
        'key': 'inkjs',
        'files': [
            './inkplay.html',
            './inkplay.js',
            './inkjs/ink.min.js',
            './inkjs/ink-130.min.js',
            './inkjs/ink-146.min.js',
            './inkjs/package.json',
        ]
    },
]

rootfiles = [
    './LICENSE',    
    './LICENSES-FONTS.txt',
]

win32_rootfiles = [
    'LICENSE',
    'LICENSES-FONTS.txt',
]

def install(resourcedir, pkg):
    if not os.path.isdir(resourcedir):
        raise Exception('path does not exist: ' + resourcedir)
    appdir = resourcedir
    print('Installing to: ' + appdir)

    soleterp = pkg.get('lectroteSoleInterpreter')

    appfilesused = []
    for val in appfiles:
        if type(val) is dict:
            if soleterp and val['key'] != soleterp:
                continue
            for filename in val['files']:
                appfilesused.append(filename)
        else:
            appfilesused.append(val)
    
    os.makedirs(appdir, exist_ok=True)
    qdir = os.path.join(appdir, 'quixe')
    os.makedirs(qdir, exist_ok=True)
    os.makedirs(os.path.join(qdir, 'lib'), exist_ok=True)
    os.makedirs(os.path.join(qdir, 'media'), exist_ok=True)
    zvmdir = os.path.join(appdir, 'ifvms')
    os.makedirs(zvmdir, exist_ok=True)
    emglkendir = os.path.join(appdir, 'emglken')
    os.makedirs(emglkendir, exist_ok=True)
    inkdir = os.path.join(appdir, 'inkjs')
    os.makedirs(inkdir, exist_ok=True)

    for filename in appfilesused:
        srcfilename = filename
        if opts.gamedir:
            val = os.path.join(opts.gamedir, filename)
            if os.path.exists(val):
                srcfilename = val

        tgtfilename = os.path.join(appdir, filename)
        if not os.path.isdir(filename):
            if not os.path.exists(tgtfilename):
                shutil.copyfile(srcfilename, tgtfilename)
        else:
            subdirname = os.path.join(appdir, filename)
            os.makedirs(subdirname, exist_ok=True)
            for subfile in os.listdir(srcfilename):
                tgtfilename = os.path.join(subdirname, subfile)
                if not os.path.exists(tgtfilename):
                    shutil.copyfile(os.path.join(srcfilename, subfile), tgtfilename)

    extrafiles = pkg.get('lectroteExtraFiles')
    if opts.gamedir and extrafiles:
        gamedir = os.path.basename(opts.gamedir)
        os.makedirs(gamedir, exist_ok=True)
        for filename in extrafiles:
            srcfilename = os.path.join(opts.gamedir, filename)
            if not os.path.isdir(filename):
                tgtfilename = os.path.join(gamedir, filename)
                if not os.path.exists(tgtfilename):
                    shutil.copyfile(srcfilename, tgtfilename)
            else:
                subdirname = os.path.join(gamedir, filename)
                os.makedirs(subdirname, exist_ok=True)
                for subfile in os.listdir(srcfilename):
                    tgtfilename = os.path.join(subdirname, subfile)
                    if not os.path.exists(tgtfilename):
                        shutil.copyfile(os.path.join(srcfilename, subfile), tgtfilename)

def builddir(dir, pack, pkg):
    (platform, dummy, arch) = pack.partition('-')

    cmd = 'node_modules/.bin/electron-packager'

    if platform == 'win32':
        cmd = 'node_modules\.bin\electron-packager'

    args = [
        cmd, product_name, product_name,
        '--app-version', product_version,
        '--build-version', opts.buildversion,
        '--arch='+arch, '--platform='+platform,
        '--out', 'dist',
        '--overwrite'
        ]

    if platform == 'darwin':
        appid = 'com.eblong.lectrote'
        if opts.gamedir:
            appid = pkg.get('lectroteMacAppID')
            if not appid:
                raise Exception('Mac package must set lectroteMacAppID')
            if appid == 'com.eblong.lectrote':
                raise Exception('lectroteMacAppID must not be com.eblong.lectrote')

        iconpath = 'resources/appicon-mac.icns'
        if opts.gamedir and os.path.exists(os.path.join(opts.gamedir, 'resources/appicon-mac.icns')):
            iconpath = os.path.join(opts.gamedir, 'resources/appicon-mac.icns')
        
        args = args + [
            '--app-bundle-id='+appid,
            '--app-category-type=public.app-category.games',
            '--icon='+iconpath,
            '--extra-resource=resources/icon-glulx.icns',
            '--extra-resource=resources/icon-zcode.icns',
            '--extra-resource=resources/icon-hugo.icns',
            '--extra-resource=resources/icon-blorb.icns',
            '--extra-resource=resources/icon-gblorb.icns',
            '--extra-resource=resources/icon-zblorb.icns',
            '--extra-resource=resources/icon-glksave.icns',
            '--extra-resource=resources/icon-glkdata.icns',
            '--extra-resource=resources/icon-json.icns',
            '--extend-info', 'resources/Add-Info.plist',
            ]

    if platform == 'win32':
        iconpath = 'resources/appicon-win.ico'
        if opts.gamedir and os.path.exists(os.path.join(opts.gamedir, 'resources/appicon-win.ico')):
            iconpath = os.path.join(opts.gamedir, 'resources/appicon-win.ico')

        filedesc = 'Interactive Fiction Interpreter'
        if opts.gamedir and pkg.get('description'):
            filedesc = pkg.get('description')

        if not opts.gamedir:
            companyname = 'Zarfhome Software'
        else:
            companyname = pkg.get('lectroteCompanyName')
        if companyname:
            args.append('--win32metadata.CompanyName='+companyname)

        if not opts.gamedir:
            copyright = 'Copyright 2016 by Andrew Plotkin'
        else:
            copyright = pkg.get('lectroteCopyright')
        if copyright:
            args.append('--app-copyright='+copyright)
        
        args = args + [
            '--win32metadata.InternalName='+product_name,
            '--win32metadata.ProductName='+product_name,
            '--win32metadata.OriginalFilename='+product_name+'.exe',
            '--win32metadata.FileDescription='+filedesc,
            '--icon='+iconpath,
            ]

        rootfiles = win32_rootfiles
        
    subprocess.call(args, shell=True)

    for filename in rootfiles:
        shutil.copyfile(filename, os.path.join(dir, filename))
    os.unlink(os.path.join(dir, 'version'))
    
def makezip(dir, zipdir, unwrapped=False):
    prefix = product_name + '-'
    val = os.path.split(dir)[-1]
    if not val.startswith(prefix):
        raise Exception('path does not have the prefix')
    zipfile = product_name + '-' + product_version + '-' + val[len(prefix):]
    zipargs = '-q'
    if 'darwin' in zipfile:
        zipfile = zipfile.replace('darwin', 'macos')
        print('AppDMGing up: %s to %s' % (dir, zipfile))
        subprocess.call('rm -f "dist/%s.dmg"; node_modules/.bin/appdmg resources/pack-dmg-spec.json "dist/%s.dmg"' % (zipfile, zipfile),
                        shell=True)
        return
    print('Zipping up: %s to %s (%s)' % (dir, zipfile, ('unwrapped' if unwrapped else 'wrapped')))
    if unwrapped:
        if 'darwin' in zipfile:
            subprocess.call('cd "%s"; rm -f "../%s.zip"; bestzip "%s" -r "../%s.zip" *' % (dir, zipfile, zipargs, zipfile), shell=True)
        if 'win32' in zipfile:
            os.chdir('dist')
            os.chdir(zipdir)
            tgtfile = '..\%s.zip' % (zipfile)
            if os.path.exists(tgtfile):
                os.remove(tgtfile)
            subprocess.call('bestzip ..\%s.zip .\\' % (zipfile), shell=True)
            os.chdir('..\\')
            os.chdir('..\\')
    else:
        dirls = os.path.split(dir)
        subdir = dirls[-1]
        topdir = os.path.join(*os.path.split(dir)[0:-1])

        if 'darwin' in zipfile:
            subprocess.call('cd "%s"; rm -f "%s.zip"; bestzip "%s" -r "%s.zip" "%s"' % (topdir, zipfile, zipargs, zipfile, subdir), shell=True)

        if 'win32' in zipfile:
            subprocess.call('cd "%s"; del /F "%s.zip"; bestzip "%s" -r "%s.zip" "%s"' % (topdir, zipfile, zipargs, zipfile, subdir), shell=True)

# Start work! First, read the version string out of package.json.

pkgfile = 'package.json'
if opts.gamedir and os.path.exists(os.path.join(opts.gamedir, 'package.json')):
    pkgfile = os.path.join(opts.gamedir, 'package.json')
fl = open(pkgfile)
pkg = json.load(fl)
fl.close()

product_version = pkg['version']
product_name = pkg['productName'];
print('%s version: %s' % (product_name, product_version,))
if product_name != 'Lectrote':
    print('%s version: %s' % ('Lectrote', pkg['lectroteVersion'],))

# Decide what distributions we're working on. ("packages" is a bit overloaded,
# sorry.)

packages = []
if not args:
    packages = all_packages
else:
    for pack in all_packages:
        for arg in args:
            if arg in pack:
                packages.append(pack)
                break

if not packages:
    raise Exception('no packages selected')

if not opts.gamedir:
    os.makedirs('tempapp', exist_ok=True)
    install('tempapp', pkg)

if opts.gamedir:
    os.makedirs(opts.gamedir, exist_ok=True)
    install(opts.gamedir, pkg)

os.makedirs('dist', exist_ok=True)

doall = not (opts.makedist or opts.makezip or opts.makenothing)

if doall or opts.makedist:
    for pack in packages:
        (platform, dummy, arch) = pack.partition('-')

        if platform == 'win32':
            dest = 'dist\%s-%s' % (product_name, pack,)
            builddir(dest, pack, pkg)

        if platform == 'darwin':
            dest = 'dist/%s-%s' % (product_name, pack,)
            builddir(dest, pack, pkg)

if doall or opts.makezip:
    for pack in packages:
        (platform, dummy, arch) = pack.partition('-')

        if platform == 'win32':
            zippath = 'dist\%s-%s' % (product_name, pack,)
            zipdir = '%s-%s' % (product_name, pack,)
            makezip(zippath, zipdir, unwrapped=('win32' in pack))

        if platform == 'darwin':
            dest = 'dist/%s-%s' % (product_name, pack,)
            makezip(dest, '', unwrapped=('win32' in pack))