GithubHelp home page GithubHelp logo

4d-tutorial-deployment's Introduction

4d-tutorial-deployment

アプリケーションビルド(Mac編)

概要

Apple Silicon/Intelネイティブのハイブリッドアーキテクチャ(Universal Binary 2)アプリをビルドし,ネットワーク経由で配付できるようにコード署名と公証に対応するための手順を説明します。アプリケーションフォルダーにインストールすることができ,ファイルシステムやネットワークにアクセスしてもクラッシュしないようなアプリをビルドするためには,こうした手順を踏む必要があります。

準備

プロジェクトを作成します。

project

c7dbedd

ポイント: ARM (Apple Silicon) ターゲットのコンパイルをするためには,プロジェクトモードでアプリケーションを開発する必要があります。バイナリモード(いわゆるストラクチャファイル)はインタープリターモード専用なので,ビルドすることができません。

コンパイル

  • 設定>ストラクチャ設定

コンパイラーページを開き,コンパイル対象CPU全てのプロセッサに設定します。

スクリーンショット 2022-08-31 13 22 28

Xcodeのインストール

ARM (Apple Silicon) ターゲットのコンパイルをするためには,Xcodeがインストールされていなければなりません。

xcode

インストール後,最初の起動時にコマンドラインツール(追加コンポーネント)のインストールが始まるはずです。コマンドラインツールがインストールされてない場合,xcode-select --installでダウンロードしてください。

スクリーンショット 2019-11-12 23 49 09

ARM (Apple Silicon) ターゲットのコンパイルをするためにXcodeのアップデートが必要な場合,下記のメッセージが表示されます。

update

HelperToolのインストールに失敗した,というメッセージが表示されることがあります。

fail

コンパイルが途中まで進んでいた場合,その回は失敗に終わるかもしれません。

error

コンパイルコードを削除して再コンパイルすれば成功するはずです。

【参考】コンポーネントの管理

コンポーネントは,プロジェクトフォルダーのComponentsフォルダーにインストールします。下記いずれかのファイル形式がサポートされています。

  1. .4DB
  2. .4DC
  3. .4DZ
  4. .4dbase
  5. プロジェクトフォルダー

.4DZはProjectフォルダーをzip圧縮したファイル形式です。コンパイルされているとは限りません。

Resourcesなどの関連フォルダーを含めるのであれば,.4dbaseまたはプロジェクトフォルダーをインストールする必要があります。

通常,コンポーネントには複数のプロジェクトに共通の汎用的なモジュールとして開発します。それぞれのプロジェクトのコンポーネントのソースコードをインストールするのでは管理が大変です。それでComponentsフォルダーにエイリアスをインストールすることが推奨されています。下記のように整理できるかもしれません。

  • Components: エイリアス
  • Components - Releases: コンパイル版のコンポーネント
  • Components - Sources: コンポーネントのソースコード

components

サンプルプロジェクトのOn Startupには,依存コンポーネントのエイリアスを作成するコードが記述されています。

cs.Startup.new().linkComponents().restartIfNecessary()

サンプルプロジェクトのコンポーネントは,下記の要領でコンパイル→ビルド→インストールができるようになっています。

BuildApp.buildComponent()

サンプルアプリケーション

ダイアログに現在時刻を表示するだけの簡単なプログラムです。

dialog

ちなみにフォームはアプリケーションプロセスで表示し,バックグラウンド処理はプリエンプティブモードのワーカーで実行しています。On Timerは使用していません。

runtime

55f2066

ユーザー設定

アプリケーションをビルドすると,データベースフォルダーのSettingsフォルダーは読み書きができなくなります。設定ファイルを外部ファイルで管理するため,ユーザー設定を有効にする必要があります。

  • データベース設定>セキュリティ>外部ファイルのユーザー設定を有効にする

スクリーンショット 2022-08-31 13 22 28

  • デザイン>設定>ユーザー設定

が管理できるようになります。

データファイルがストラクチャファイルとは別の場所にあれば,

  • デザイン>設定>データファイル用のユーザー設定

も管理できるようになります。

  • 設定>ストラクチャ設定

一般ページを開き,起動時モードアプリケーションに設定します。この項目はストラクチャレベルで設定する必要があります。

スクリーンショット 2022-08-31 10 53 17

アプリケーションモードのスプラッシュ画面が不要であれば,インターフェースページを開き,ウィンドウの表示スプラッシュスクリーンを解除します。

スクリーンショット 2022-08-31 13 20 12

eec39b1

  • ツールボックス>メニュー

モードメニューを削除します。

スクリーンショット 2022-08-31 13 21 06

注記: デザインモードにはoption+command+右クリックで移動できます。

アバウト画面

SET ABOUTを使用し,「4Dについて」画面をカスタマイズします。

スクリーンショット 2022-08-31 11 31 32

デフォルトデータファイル

プロジェクトフォルダーにDefault Data/default.4DDというフォルダーが存在する場合,内容がビルドアプリケーション内にコピーされ,デフォルトのデータファイルとしてリードオンリーモードで使用されるようになっています。

  • Default Dataフォルダーを作成し,下記の項目をコピーします。

  • データファイル default.4DD default.Match

  • インデックスファイル default.4DIndx

  • 設定フォルダー Settings

スクリーンショット 2022-08-31 12 35 33

データファイルを切り替える条件が満たされているかチェックするコードをスタートアップで実行します。

  • (Version type ?? Merged application)
  • (Application type=4D Volume desktop) | (Application type=4D Server)
  • (Data file=Folder(Get 4D folder(Database folder);fk platform path).folder("Default Data").file("default.4DD").platformPath)
  • (Is data file locked)

上記の条件が満たされたなら,OPEN DATA FILEまたはCREATE DATA FILEで運用データファイルを作成または使用します。これらのコマンドはアプリケーション再起動前に実行される最後のコマンドであるべきです。既存のスタートアップコードとは相互に排他的な処理になるようにプログラムする必要があります。

  • ユーザー設定ファイルもデフォルトデータフォルダーから運用データファイルにコピーします。

ログファイル

  • デザイン>設定>データファイル用のユーザー設定

バックアップページを開き,ログを使用を解除します。

スクリーンショット 2022-08-31 11 59 49

デフォルトデータファイルを使用している間は,データベースが書き込み保護されており,まだログファイルを有効にすることはできません。運用データファイルに切り替わった後,ログファイルを使用する条件が満たされているかチェックするコードをスタートアップで実行します。

  • (Version type ?? Merged application)
  • (Application type=4D Volume desktop) | (Application type=4D Server)
  • (Log file="")
  • (Not(Is data file locked))

SELECT LOG FILEでログファイルを作成する場所を決定します。ログファイルは次回のバックアップ完了後から使用されるようになります。

アイコンファイル

アプリのアイコンをカスタマイズするには,Finderの「情報を見る」ダイアログではなく,ビルドプロジェクトのServerIconMacPath RuntimeVLIconMacPath ClientMacIconForMacPathを使用し,icnsファイルのパスを指定します。icnsファイルを作成するには,必要なサイズの.png画像を.iconsetという拡張子のフォルダーに入れ,下記のコマンドラインを実行します。

iconutil -c <path>

単一フレームのicns画像では,カスタムアイコンが表示されません。.png画像は,sipsでリサイズすることができます。

sips -z <pixelsH> <pixelsW> <path>

c.f. Macアプリの.icnsを作るときのメモ

コード署名と公証

初期のMac OS Xでは,作成したアプリを.zip .pkg .dmgなどのファイル形式に圧縮し,ユーザーのマシンにダウンロードしてインストールすることができました。Mac OS X 10.7 Lion以降,ユーザーがインターネットからダウンロードしたアプリは,システムに統合された防御機構(GateKeeper)が初回の起動時にセキュリティのチェックを実施します。GateKeeperの設定は,システム環境設定の「セキュリティとプライバシー(一般)」で確認および変更することができます。

10.8 Mountain Lion以降,デフォルトの設定は「App Storeと確認済みの開発元からのアプリケーションを許可」です。App Storeではない場所からダウンロードしたアプリは,Apple Developer Program に登録された開発元の有効なコード署名が確認できない場合,GateKeeperは起動をブロックします。

10.15 Catalina以降,コード署名に加え,公証ノータリゼーション)が確認できないアプリは,デフォルトで起動を許可しない設定になりました。公証とは,プログラムがマルウェアのように自己を改竄したりしないことを保証するために,Appleが運営している申告・判定・登録システムのことです。GateKeeperは,初回の起動でアプリが公証にパスしたことを証明する電子的なチケット(ステープル)の存在をチェックします。チケットが確認できない場合,Appleのサーバーにアクセスし,そのアプリが公証にパスしたものかどうか,公証データベースに問い合わせます。

4Dおよび4D Serverは署名されていますが,ビルドしたアプリは,4Dから派生した「別アプリ」に該当するため,デベロッパー各自が署名や公証を実施しなければなりません。具体的には,下記のリソースに署名を実施し,公証のチケットを発行してもらうことが必要です。

  • ビルドアプリ(本体)
  • 4Dに標準で付属しているアプリ(Updater InstallTool [17r5以降])
  • 4Dに標準で付属している実行ファイル(php-fcgi-4d HelperTool InstallTool [17r4以前])
  • その他の実行バンドル(フレームワーク・プラグイン)
  • その他の実行ファイル(.js .html .json LAUNCH EXTERNAL PROCESSで起動する外部プログラム)

コード署名が確認できた場合,下記のようなメッセージが初回の起動時にだけ表示されます。

…はインターネットからダウンロードされたアプリケーションです。開いてもよろしいですか?
このファイルは"Safari"により…ダウンロードされました。

コード署名が確認できない場合,下記のような警告メッセージが表示されます。

…は,開発元を検証できないため開けません。
このアプリケーションにマルウェアが含まれていないことを検証できません。

ユーザーは,開発元が信頼できると判断できる場合,controlキーを押しながらアプリをクリックし,「Mac のセキュリティ設定を一時的に無視して」アプリを起動することができます。また,インターネット経由ではなく,接続した外部ドライブ等からコピーしたファイルであれば,そのまま開くことができます。ですから,4Dで開発したアプリを配付するために,署名と公証が絶対に必要というわけではありません。それでも,利便性とユーザーエクスペリンスの観点から,実施することが勧められています。

コード署名に問題がある場合,下記のような警告メッセージが表示されます。このようなアプリを開くことはできません。

…は,壊れているため開けません。ゴミ箱に入れる必要があります。
このファイルは"Safari"により…ダウンロードされました。

下記のようなコマンドをターミナルに入力し検疫フラグ(アプリがネットワーク経由でダウンロードされたという印)や問題のあるコード署名を取り除くことができます。

xattr -cr {application_path}
codesign --remove-signature {application_path}

署名と公証を実施するために必要なものは下記のとおりです。

Apple Developer Program

Apple Developer Programには,無料のプログラムも用意されていますが,「App StoreでのApp配信」および「Mac App Store以外でのソフトウェア配信」が特典に含まれていません。無料のメンバーシップでは,Developer ID 証明書の発行ができないためです。署名と公証には,Developer ID 証明書が必要です。

Apple ID

Apple IDは,Mac,iOSデバイス,アプリ,オンラインいずれかの方法で作成することができます。Macユーザーであれば,すでに保有しているかもしれません。

アプリ開発用に新しいアカウントを作成することもできますが,2ファクタ認証を有効にする必要があり,原則的に2台以上のApple機器で同じApple IDを使用していることが想定されているので,個人のApple IDをそのまま使用したほうが簡単かもしれません。

注記: Apple機器が1台だけの場合,電話で2ファクタ認証を完了することができます。

2ファクタ認証

2ファクタ認証は,古典的なユーザー名とパスワードの組み合わせを知っていること(第1ファクター:知識)に加え,当該ユーザーの個人的な電子機器を持っていること(第2ファクター:デバイス)を本人確認の根拠にするという仕組みです。具体的には,6桁の確認コードを電話などに送信し,入力させることにより,ユーザーを認証します。Apple IDの場合,2ファクターは任意ですが,Apple Developer IDの場合,2ファクターは必須となっています。

Apple IDでログインして,Apple Developer Programに加入の手続きを開始します。2ファクタ認証が有効にされていなければ,このとき設定を済ませるよう案内されます。支払いが完了すると,数時間後に手続き完了の通知メールが送られるはずです。

最新版のmacOSおよびXcodeは,App Storeから入手することができます。古いバージョンのXcodeがアプリケーションフォルダーにインストールされている場合,アプリケーションは上書きされます。以前のXcodeを残しておきたいのであれば,サブフォルダーなど,あらかじめ別の場所に退避してください。

注記: Apple Developerにログインすると,開発中(ベータ版)および旧バージョンのソフトウェアがダウンロードできます。

コマンドラインツール

4Dアプリの署名と公証は,Xcodeアプリではなく,コマンドラインツール経由で実施します。Xcodeのコマンドラインツールは,xcrunコマンドを介して実行します。xcrunはデフォルトの場所にインストールされているXcodeの内部にあるプログラムを実行するようになっています。デフォルトのパスは下記のコマンドラインで確認することができます。

xcode-select -p

複数のXcodeがインストールされている場合,あるいは標準的ではない場所にXcodeがインストールされている場合,

xcode-select --switch <path>

ただし,他の開発ツールに影響を与える恐れがあるので,環境変数のDEVELOPER_DIRで一時的にパスを変更したほうが無難かもしれません。

電子証明書

Xcodeを起動し,アプリケーションメニューの「Preferences」から「Accounts」のページを開きます。Developer IDを入力し,ログインします。

スクリーンショット 2019-10-17 17 00 06

「Manage Certificates」をクリックし,画面の左下にある「+」アイコンをクリックして,「Developer ID Application」および「Developer ID Installer」証明書を作成します。

注記: 無料のApple Developer IDでログインしている場合,Developer ID系の証明書は作成できません。「Mac Developer」証明書は作成できますが,これは個人のデバイスでアプリをテストするための証明書であり,アプリを配付する目的では使用できないものです。

スクリーンショット 2019-10-17 17 06 07

配付用アプリの公証は,ビルド毎に実行する必要があるので,自動化しておくと便利です。その場合,パスワードの入力を自動化するために,App用パスワードを作成しておきます。パスワードは,Apple IDのアカウントページにログインし,「セキュリティ」セクションの「App 用パスワード」の下の「パスワードを生成」をクリックすれば自動的に作成されます。「このパスワードのラベルを入力」には,後で参照できる簡単な文字列(例:abcde)を入力します。

appleid.apple.comにログインします。

スクリーンショット 2019-11-07 16 50 34

2ファクタ認証のサインインを許可します。

スクリーンショット 2019-11-07 16 52 07

スクリーンショット 2019-11-07 16 53 00

スクリーンショット 2019-11-07 16 53 32

セキュリティに移動します。

スクリーンショット 2019-11-07 16 57 07

**パスワードを生成…**をクリックします。

パスワードのラベルには任意の英数字(空白はOK,記号はNG)を入力します。

スクリーンショット 2019-11-12 23 57 55

App用パスワードは25まで作成することができます。

セキュリティの「編集」ボタンをクリックすると,App用パスワードの履歴を表示することができ,削除することもできます。ラベルは,この画面でパスワードを管理するためのものです。同じラベルを使用しても,毎回,違うパスワードが発行されます。

スクリーンショット 2019-11-07 17 19 32

コード署名ツール

コード署名には下記いずれかのツールを使用します。

  • altool(旧)
  • notarytool(新)

署名には,前述の手順で作成したpp用パスワードが必要です。そのままパラメーターに渡すこともできますが,できればパスワードをキーチェーンに保存し,登録名で参照することが勧められています。

  • altool
xcrun altool --store-password-in-keychain-item <item_name> -u <apple_developer_id> -p <secret_password>

これにより,キーチェーンにアプリ用のパスワードが保存され,下記のようなコマンドラインでパスワードが参照できるようになります。

xcrun altool --notarize-app -u <apple_developer_id> -p "@keychain:<item_name>"
  • notarytool
xcrun notarytool store-credentials <item_name> --apple-id <apple_developer_id> --team-id <apple_developer_team_id> --password <secret_password>

これにより,キーチェーンにアプリ用のパスワードが保存され,下記のようなコマンドラインでパスワードが参照できるようになります。

xcrun notarytool --keychain-profile <item_name>

エンタイトルメント

アプリのコード署名には,アプリの実行に必要なエンタイトルメントが組み込まれることになっています。エンタイトルメントは,XML形式のプロパティリスト(.plist)で編集します。XML形式の.plistをそのままコード署名に使用することはできません。バイナリ形式の.plistに変換する必要があります。ファイル形式を変換するには,下記のようなコマンドラインを実行します。

plutil -convert xml1 <path>

エンタイトルメントを必要とするようなアプリは,マルウェアではないことを保証するため,書き込みが禁止された実行環境(Hardened Runtime)で動作することが求められています。

4Dの場合,アプリ本体に加え,php-fcgi-4d HelperTool Updater InstallToolといった実行ファイルが組み込まれているため,それぞれに対し,Hardened Runtimeオプションを付けてコード署名を実施する必要があります。

codesign --options=runtime --entitlements <path>

プラグイン・フレームワーク・ライブラリなど,実行ファイルがロードする個別のファイルにHardened Runtimeオプションを付ける必要はありません。

タイムスタンプ

公証アプリは,セキュアなタイムスタンプを付けて署名されていなければなりません。そのためには,インターネットに接続された状態でcodesignを実行し,下記のオプションを指定する必要があります。

codesign --timestamp

プラットフォームSDK

公証アプリは,macOS 10.9 SDK以降で開発されていなければなりません。4D本体は,この条件をクリアしていますが,個別のプラグイン・フレームワーク・ライブラリはそうではないかもしれません。そのような場合,macOS 10.9 SDK以降で再コンパイルする必要があります。

アプリ・プラグイン・フレームワークなどの「バンドル」フォルダーは,再帰的にコード署名を実施することができます。

codesign --deep

--deepオプションは,すでに署名されているリソースの署名は上書きしません。コード署名は,原則的にフォルダー構造の中から外に向かって実施します。4Dの場合,プリインストールされたアプリや実行ファイルにはエンタイトルメントとHardened Runtimeオプションを指定して署名します。プラグイン・フレームワーク・ライブラリなどのリソースは,エンタイトルメントを指定せずにコード署名を実施します。最後に外殻のアプリ本体を署名しますが,このとき--force(強制的に署名)オプションを指定してしまうと,内部リソースの署名が無効になってしまうので,すでに署名が済んでいるリソースの外部では--forceオプションを指定はしないでください。

バンドル識別子

4Dプラグインには,歴史的な経緯により,4DCBというバンドル識別子(CFBundlePackageType)が設定されていました。Appleの公証は,BNDL APPL FMWKのような標準バンドル識別子でなければ,包括的なチェックを実施しないようです。プラグインのバンドル識別子は,BNDLに設定する必要があります。

アプリ・プラグイン・フレームワークなどの「バンドル」の内部には,Info.plistという名称のカタログファイルが存在します。このファイルには,バンドルの基本的な情報が辞書形式(キー/値ペア)で書き込まれていますが,CFBundleName CFBundleExecutable 等のキー値が実際のファイル名と完全に一致しない場合,たとえば小文字の代わりに大文字が使用されている場合,コード署名エラーになります。

invalid Info.plist (plist or signature have been modified)

コード署名に使用する証明書が署名のアイデンティーとなります。アプリに署名するのであれば,Developer ID Application:…証明書,インストーラーに署名するのであれば,Developer ID Installer:…証明書をアイデンティーとして使用します。

キーチェーンに登録されている証明書は,下記のコマンドラインでリストアップすることができます。

security find-identity -p basic -v

ステープル

ユーザーがアプリをダウンロードした後,初回の起動でアプリが公証にパスしたことを証明する電子的なチケット(ステープル)の存在をチェックします。チケットが確認できない場合,Appleのサーバーにアクセスし,そのアプリが公証にパスしたものかどうか,公証データベースに問い合わせます。

下記のコマンドラインでチケットをアプリに紐付ける(ステープルする)ことができます。アプリが公証にパスした後でなければ,ステープルはできません。紐付けは,ディスクイメージやインストーラーではなく,アプリ自体に対して実行します。コマンドは,インターネットに接続された状態で実行する必要があります。

xcrun stapler staple <path>

サンプルプログラムにインストールされているbuilderコンポーネントのSignAppクラスには,コード署名や公証に必要なコマンドラインツールが実装されています。

  • altool - 公証
  • notarytool - 公証
  • stapler - ステープル
  • codesign - コード署名
  • ditto - .zipを作成
  • hdiutil - .dmgを作成
  • install_name_tool - ダイナミックリンクライブラリの参照パスを書き換え
  • pkgbuild - .pkgの作成
  • productsign - .pkgの署名
  • xcode-select - Xcodeの管理
  • security - キーチェーンの検索
  • plutil - プロパティリストの編集

コンポーネントを使用すれば,オブジェクト指向のシンプルなAPIでコード署名と公証を済ませることができます。→例題

ビルド

デザインモードのアプリケーションビルド画面を使用すれば,基本的な項目が設定できます。より細かくビルド過程を制御するためには,作成したビルド設定XMLファイルとBUILD APPLICATIONコマンドを使用し,ログファイルを解析することが求められます。

サンプルプログラムにインストールされているbuilderコンポーネントのBuildAppクラスには,BUILD APPLICATIONコマンドの全オプションが実装されています。

コンポーネントを使用すれば,オブジェクト指向のシンプルなAPIでビルドを済ませることができます。→例題

例題

buildコンポーネントtest_buildメソッド

/*
	
	* ビルド
	
*/

$buildApp:=cs.BuildApp.new()

$buildApp.findLicenses(New collection("4DOE"; "4UOE"; "4DDP"; "4UUD"))
$isOEM:=($buildApp.settings.Licenses.ArrayLicenseMac.Item.indexOf("@:4DOE@")#-1)

$buildApp.settings.BuildApplicationName:=Folder(fk database folder).name
$buildApp.settings.BuildApplicationSerialized:=True
$buildApp.settings.BuildMacDestFolder:=Temporary folder+Generate UUID
$buildApp.settings.SourcesFiles.RuntimeVL.RuntimeVLIncludeIt:=True
$buildApp.settings.SourcesFiles.RuntimeVL.RuntimeVLMacFolder:=$buildApp.getAppFolderForVersion().folder("4D Volume Desktop.app").platformPath
$buildApp.settings.SourcesFiles.RuntimeVL.IsOEM:=$isOEM
$buildApp.settings.SignApplication.MacSignature:=False
$buildApp.settings.SignApplication.AdHocSign:=False

$status:=$buildApp.build()

/*
	
	署名
	
*/

$credentials:=New object
$credentials.username:="[email protected]"
$credentials.password:="@keychain:altool"
$credentials.keychainProfile:="notarytool"
$credentials.certificateName:="Developer ID Application: keisuke miyako (Y69CWUC25B)"

$signApp:=cs.SignApp.new($credentials)

$app:=Folder($buildApp.settings.BuildMacDestFolder; fk platform path).folder("Final Application").folder($buildApp.settings.BuildApplicationName+".app")

$status.sign:=$signApp.sign($app)

/*
	
	公証 
	
*/

$status.archive:=$signApp.archive($app; ".pkg")

$status.notarize:=$signApp.notarize($status.archive.file)

サンプルビルド

test_build_appメソッドを実行して.pkgまたは.dmg形式の署名/公証アーカイブを作成しました。

0.0.20

$build:=cs.Build.new()
$build.versionString:=cs.Version.new().updatePatch().getString()
$status:=$build.buildDesktop(".dmg")

If ($status.build.success)
	If ($status.archive.success)
		If ($status.notarize.success)
			SHOW ON DISK($status.app.platformPath)
		End if 
	End if 
End if 

505bca8

  • updatePatch(): パッチ番号をインクリメントします。このバージョンコードがInfo.plistに書き込まれます。
  • buildDesktop(): ビルド/署名/アーカイブ/公証まで一連の処理を実行します。

例題(サンドボックス)

0.0.26

0.0.27

$app:=cs.App.new()
$appName:=$app.getName()

$build:=cs.Build.new()
$build.versionString:=cs.Version.new().updatePatch().getString()
$build.certificateName:="Apple Distribution: keisuke miyako (Y69CWUC25B)"
$build.desktopAppIdentifier:="org.fourd."+$appName
$build.entitlements:=New object

$build.entitlements["com.apple.security.app-sandbox"]:=False
$build.entitlements["com.apple.security.application-groups"]:=New collection("Y69CWUC25B.org.fourd")
$build.entitlements["com.apple.security.inherit"]:=True
$build.entitlements["com.apple.security.network.client"]:=True
$build.entitlements["com.apple.security.network.server"]:=True
$build.entitlements["com.apple.security.files.user-selected.read-write"]:=True
$build.entitlements["com.apple.security.files.user-selected.executable"]:=True

$status:=$build.buildDesktop(".pkg")

If ($status.build.success)
	If ($status.archive.success)
		If ($status.notarize.success)
			SHOW ON DISK($status.app.platformPath)
		End if 
	End if 
End if 

cda6ad8

資料/文献

4d-tutorial-deployment's People

Contributors

miyako avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.