Add python setup script
This commit is contained in:
parent
d266705655
commit
2c1dd67b5e
459
Internal/os_clang_format_style_file
Normal file
459
Internal/os_clang_format_style_file
Normal file
@ -0,0 +1,459 @@
|
|||||||
|
---
|
||||||
|
IndentWidth: 4
|
||||||
|
TabWidth: 4
|
||||||
|
---
|
||||||
|
Language: Cpp
|
||||||
|
|
||||||
|
# Align parameters on the open bracket, e.g.:
|
||||||
|
# someLongFunction(argument1,
|
||||||
|
# argument2);
|
||||||
|
AlignAfterOpenBracket: Align
|
||||||
|
|
||||||
|
# Align array column and left justify the columns e.g.:
|
||||||
|
# struct test demo[] =
|
||||||
|
# {
|
||||||
|
# {56, 23, "hello"},
|
||||||
|
# {-1, 93463, "world"},
|
||||||
|
# {7, 5, "!!" }
|
||||||
|
# };
|
||||||
|
AlignArrayOfStructures: Left
|
||||||
|
|
||||||
|
# Align assignments on consecutive lines. This will result in formattings like:
|
||||||
|
#
|
||||||
|
# int a = 1;
|
||||||
|
# int somelongname = 2;
|
||||||
|
# double c = 3;
|
||||||
|
#
|
||||||
|
# int d = 3;
|
||||||
|
# /* A comment. */
|
||||||
|
# double e = 4;
|
||||||
|
AlignConsecutiveAssignments: Consecutive
|
||||||
|
AlignConsecutiveBitFields: Consecutive
|
||||||
|
AlignConsecutiveDeclarations: Consecutive
|
||||||
|
AlignConsecutiveMacros: Consecutive
|
||||||
|
|
||||||
|
# Align escaped newlines as far left as possible.
|
||||||
|
# #define A \
|
||||||
|
# int aaaa; \
|
||||||
|
# int b; \
|
||||||
|
# int dddddddddd;
|
||||||
|
AlignEscapedNewlines: Left
|
||||||
|
|
||||||
|
# Horizontally align operands of binary and ternary expressions.
|
||||||
|
# Specifically, this aligns operands of a single expression that needs to be
|
||||||
|
# split over multiple lines, e.g.:
|
||||||
|
#
|
||||||
|
# int aaa = bbbbbbbbbbbbbbb +
|
||||||
|
# ccccccccccccccc;
|
||||||
|
AlignOperands: Align
|
||||||
|
|
||||||
|
# true: false:
|
||||||
|
# int a; // My comment a vs. int a; // My comment a
|
||||||
|
# int b = 2; // comment b int b = 2; // comment about b
|
||||||
|
AlignTrailingComments: true
|
||||||
|
|
||||||
|
# If the function declaration doesn’t fit on a line, allow putting all
|
||||||
|
# parameters of a function declaration onto the next line even if
|
||||||
|
# BinPackParameters is false.
|
||||||
|
#
|
||||||
|
# true:
|
||||||
|
# void myFunction(
|
||||||
|
# int a, int b, int c, int d, int e);
|
||||||
|
#
|
||||||
|
# false:
|
||||||
|
# void myFunction(int a,
|
||||||
|
# int b,
|
||||||
|
# int c,
|
||||||
|
# int d,
|
||||||
|
# int e);
|
||||||
|
AllowAllParametersOfDeclarationOnNextLine: false
|
||||||
|
AllowShortBlocksOnASingleLine: Never # "while (true) { continue; }" can be put on a single line.
|
||||||
|
|
||||||
|
# If true, short case labels will be contracted to a single line.
|
||||||
|
#
|
||||||
|
# true: false:
|
||||||
|
# switch (a) { vs. switch (a) {
|
||||||
|
# case 1: x = 1; break; case 1:
|
||||||
|
# case 2: return; x = 1;
|
||||||
|
# } break;
|
||||||
|
# case 2:
|
||||||
|
# return;
|
||||||
|
# }
|
||||||
|
AllowShortCaseLabelsOnASingleLine: true
|
||||||
|
AllowShortEnumsOnASingleLine: true # enum { A, B } myEnum;
|
||||||
|
|
||||||
|
# Only merge functions defined inside a class. Implies “empty”.
|
||||||
|
#
|
||||||
|
# class Foo {
|
||||||
|
# void f() { foo(); }
|
||||||
|
# };
|
||||||
|
# void f() {
|
||||||
|
# foo();
|
||||||
|
# }
|
||||||
|
# void f() {}
|
||||||
|
AllowShortFunctionsOnASingleLine: Inline
|
||||||
|
AllowShortIfStatementsOnASingleLine: false
|
||||||
|
|
||||||
|
# Only merge empty lambdas.
|
||||||
|
#
|
||||||
|
# auto lambda = [](int a) {}
|
||||||
|
# auto lambda2 = [](int a) {
|
||||||
|
# return a;
|
||||||
|
# };
|
||||||
|
AllowShortLambdasOnASingleLine: Empty
|
||||||
|
AllowShortLoopsOnASingleLine: false
|
||||||
|
|
||||||
|
# true: false:
|
||||||
|
# aaaa = vs. aaaa = "bbbb"
|
||||||
|
# "bbbb" "cccc";
|
||||||
|
# "cccc";
|
||||||
|
AlwaysBreakBeforeMultilineStrings: true
|
||||||
|
|
||||||
|
# Force break after template declaration only when the following declaration
|
||||||
|
# spans multiple lines.
|
||||||
|
#
|
||||||
|
# template <typename T> T foo() {
|
||||||
|
# }
|
||||||
|
# template <typename T>
|
||||||
|
# T foo(int aaaaaaaaaaaaaaaaaaaaa,
|
||||||
|
# int bbbbbbbbbbbbbbbbbbbbb) {
|
||||||
|
# }
|
||||||
|
AlwaysBreakTemplateDeclarations: MultiLine
|
||||||
|
|
||||||
|
# If false, a function call’s arguments will either be all on the same line or
|
||||||
|
# will have one line each.
|
||||||
|
#
|
||||||
|
# true:
|
||||||
|
# void f() {
|
||||||
|
# f(aaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaaa,
|
||||||
|
# aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa);
|
||||||
|
# }
|
||||||
|
#
|
||||||
|
# false:
|
||||||
|
# void f() {
|
||||||
|
# f(aaaaaaaaaaaaaaaaaaaa,
|
||||||
|
# aaaaaaaaaaaaaaaaaaaa,
|
||||||
|
# aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa);
|
||||||
|
# }
|
||||||
|
BinPackArguments: false
|
||||||
|
BinPackParameters: false # As BinPackArguments but for function definition parameters
|
||||||
|
|
||||||
|
# Add space after the : only (space may be added before if needed for
|
||||||
|
# AlignConsecutiveBitFields).
|
||||||
|
#
|
||||||
|
# unsigned bf: 2;
|
||||||
|
BitFieldColonSpacing: After
|
||||||
|
|
||||||
|
# LooooooooooongType loooooooooooooooooooooongVariable =
|
||||||
|
# someLooooooooooooooooongFunction();
|
||||||
|
#
|
||||||
|
# bool value = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +
|
||||||
|
# aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ==
|
||||||
|
# aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa &&
|
||||||
|
# aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa >
|
||||||
|
# ccccccccccccccccccccccccccccccccccccccccc;
|
||||||
|
BreakBeforeBinaryOperators: None
|
||||||
|
|
||||||
|
# Always attach braces to surrounding context, but break before braces on
|
||||||
|
# function, namespace and class definitions.
|
||||||
|
BreakBeforeBraces: Linux
|
||||||
|
|
||||||
|
# true:
|
||||||
|
# template<typename T>
|
||||||
|
# concept ...
|
||||||
|
#
|
||||||
|
# false:
|
||||||
|
# template<typename T> concept ...
|
||||||
|
BreakBeforeConceptDeclarations: false
|
||||||
|
|
||||||
|
# true:
|
||||||
|
# veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongDescription
|
||||||
|
# ? firstValue
|
||||||
|
# : SecondValueVeryVeryVeryVeryLong;
|
||||||
|
#
|
||||||
|
# false:
|
||||||
|
# veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongDescription ?
|
||||||
|
# firstValue :
|
||||||
|
# SecondValueVeryVeryVeryVeryLong;
|
||||||
|
BreakBeforeTernaryOperators: true
|
||||||
|
|
||||||
|
# Break constructor initializers before the colon and commas, and align the
|
||||||
|
# commas with the colon.
|
||||||
|
#
|
||||||
|
# Constructor()
|
||||||
|
# : initializer1()
|
||||||
|
# , initializer2()
|
||||||
|
BreakConstructorInitializers: BeforeComma
|
||||||
|
|
||||||
|
# Break inheritance list only after the commas.
|
||||||
|
#
|
||||||
|
# class Foo : Base1,
|
||||||
|
# Base2
|
||||||
|
# {};
|
||||||
|
BreakInheritanceList: AfterComma
|
||||||
|
|
||||||
|
# true:
|
||||||
|
# const char* x = "veryVeryVeryVeryVeryVe"
|
||||||
|
# "ryVeryVeryVeryVeryVery"
|
||||||
|
# "VeryLongString";
|
||||||
|
BreakStringLiterals: true
|
||||||
|
ColumnLimit: 100
|
||||||
|
|
||||||
|
# false:
|
||||||
|
# namespace Foo {
|
||||||
|
# namespace Bar {
|
||||||
|
# }
|
||||||
|
# }
|
||||||
|
CompactNamespaces: false
|
||||||
|
|
||||||
|
# true: false:
|
||||||
|
# vector<int> x{1, 2, 3, 4}; vs. vector<int> x{ 1, 2, 3, 4 };
|
||||||
|
# vector<T> x{{}, {}, {}, {}}; vector<T> x{ {}, {}, {}, {} };
|
||||||
|
# f(MyMap[{composite, key}]); f(MyMap[{ composite, key }]);
|
||||||
|
# new int[3]{1, 2, 3}; new int[3]{ 1, 2, 3 };
|
||||||
|
Cpp11BracedListStyle: true
|
||||||
|
|
||||||
|
# Analyze the formatted file for the most used line ending (\r\n or \n). UseCRLF
|
||||||
|
# is only used as a fallback if none can be derived.
|
||||||
|
DeriveLineEnding: true
|
||||||
|
DerivePointerAlignment: true # As per DeriveLineEnding except for pointers and references
|
||||||
|
|
||||||
|
# Add empty line only when access modifier starts a new logical block. Logical
|
||||||
|
# block is a group of one or more member fields or functions.
|
||||||
|
#
|
||||||
|
# struct foo {
|
||||||
|
# private:
|
||||||
|
# int i;
|
||||||
|
#
|
||||||
|
# protected:
|
||||||
|
# int j;
|
||||||
|
# /* comment */
|
||||||
|
# public:
|
||||||
|
# foo() {}
|
||||||
|
#
|
||||||
|
# private:
|
||||||
|
# protected:
|
||||||
|
# };
|
||||||
|
EmptyLineBeforeAccessModifier: LogicalBlock
|
||||||
|
|
||||||
|
# true: false:
|
||||||
|
# namespace a { vs. namespace a {
|
||||||
|
# foo(); foo();
|
||||||
|
# bar(); bar();
|
||||||
|
# } // namespace a }
|
||||||
|
FixNamespaceComments: true
|
||||||
|
|
||||||
|
# false: true:
|
||||||
|
# class C { vs. class C {
|
||||||
|
# class D { class D {
|
||||||
|
# void bar(); void bar();
|
||||||
|
# protected: protected:
|
||||||
|
# D(); D();
|
||||||
|
# }; };
|
||||||
|
# public: public:
|
||||||
|
# C(); C();
|
||||||
|
# }; };
|
||||||
|
# void foo() { void foo() {
|
||||||
|
# return 1; return 1;
|
||||||
|
# } }
|
||||||
|
IndentAccessModifiers: false
|
||||||
|
|
||||||
|
# false: true:
|
||||||
|
# switch (fool) { vs. switch (fool) {
|
||||||
|
# case 1: { case 1:
|
||||||
|
# bar(); {
|
||||||
|
# } break; bar();
|
||||||
|
# default: { }
|
||||||
|
# plop(); break;
|
||||||
|
# } default:
|
||||||
|
# } {
|
||||||
|
# plop();
|
||||||
|
# }
|
||||||
|
# }
|
||||||
|
IndentCaseBlocks: false
|
||||||
|
|
||||||
|
# false: true:
|
||||||
|
# switch (fool) { vs. switch (fool) {
|
||||||
|
# case 1: case 1:
|
||||||
|
# bar(); bar();
|
||||||
|
# break; break;
|
||||||
|
# default: default:
|
||||||
|
# plop(); plop();
|
||||||
|
# } }
|
||||||
|
IndentCaseLabels: true
|
||||||
|
|
||||||
|
# extern "C" {
|
||||||
|
# void foo();
|
||||||
|
# }
|
||||||
|
IndentExternBlock: NoIndent
|
||||||
|
|
||||||
|
# Indents directives before the hash.
|
||||||
|
#
|
||||||
|
# #if FOO
|
||||||
|
# #if BAR
|
||||||
|
# #include <foo>
|
||||||
|
# #endif
|
||||||
|
# #endif
|
||||||
|
IndentPPDirectives: BeforeHash
|
||||||
|
|
||||||
|
# true: false:
|
||||||
|
# if (foo) { vs. if (foo) {
|
||||||
|
# bar();
|
||||||
|
# bar(); }
|
||||||
|
# }
|
||||||
|
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||||
|
|
||||||
|
# The maximum number of consecutive empty lines to keep.
|
||||||
|
#
|
||||||
|
# MaxEmptyLinesToKeep: 1 vs. MaxEmptyLinesToKeep: 0
|
||||||
|
# int f() { int f() {
|
||||||
|
# int = 1; int i = 1;
|
||||||
|
# i = foo();
|
||||||
|
# i = foo(); return i;
|
||||||
|
# }
|
||||||
|
# return i;
|
||||||
|
# }
|
||||||
|
MaxEmptyLinesToKeep: 1
|
||||||
|
NamespaceIndentation: None
|
||||||
|
|
||||||
|
# Put all constructor initializers on the current line if they fit. Otherwise,
|
||||||
|
# put each one on its own line.
|
||||||
|
#
|
||||||
|
# Constructor() : a(), b()
|
||||||
|
#
|
||||||
|
# Constructor()
|
||||||
|
# : aaaaaaaaaaaaaaaaaaaa(),
|
||||||
|
# bbbbbbbbbbbbbbbbbbbb(),
|
||||||
|
# ddddddddddddd()
|
||||||
|
PackConstructorInitializers: CurrentLine
|
||||||
|
PointerAlignment: Right
|
||||||
|
|
||||||
|
# false:
|
||||||
|
# // veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of information
|
||||||
|
# /* second veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of information */
|
||||||
|
#
|
||||||
|
# true:
|
||||||
|
# // veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of
|
||||||
|
# // information
|
||||||
|
# /* second veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of
|
||||||
|
# * information */
|
||||||
|
ReflowComments: true
|
||||||
|
|
||||||
|
# false: true:
|
||||||
|
#
|
||||||
|
# if (isa<FunctionDecl>(D)) { vs. if (isa<FunctionDecl>(D))
|
||||||
|
# handleFunctionDecl(D); handleFunctionDecl(D);
|
||||||
|
# } else if (isa<VarDecl>(D)) { else if (isa<VarDecl>(D))
|
||||||
|
# handleVarDecl(D); handleVarDecl(D);
|
||||||
|
# }
|
||||||
|
#
|
||||||
|
# if (isa<VarDecl>(D)) { vs. if (isa<VarDecl>(D)) {
|
||||||
|
# for (auto *A : D.attrs()) { for (auto *A : D.attrs())
|
||||||
|
# if (shouldProcessAttr(A)) { if (shouldProcessAttr(A))
|
||||||
|
# handleAttr(A); handleAttr(A);
|
||||||
|
# } }
|
||||||
|
# }
|
||||||
|
# }
|
||||||
|
#
|
||||||
|
# if (isa<FunctionDecl>(D)) { vs. if (isa<FunctionDecl>(D))
|
||||||
|
# for (auto *A : D.attrs()) { for (auto *A : D.attrs())
|
||||||
|
# handleAttr(A); handleAttr(A);
|
||||||
|
# }
|
||||||
|
# }
|
||||||
|
#
|
||||||
|
# if (auto *D = (T)(D)) { vs. if (auto *D = (T)(D)) {
|
||||||
|
# if (shouldProcess(D)) { if (shouldProcess(D))
|
||||||
|
# handleVarDecl(D); handleVarDecl(D);
|
||||||
|
# } else { else
|
||||||
|
# markAsIgnored(D); markAsIgnored(D);
|
||||||
|
# } }
|
||||||
|
# }
|
||||||
|
#
|
||||||
|
# if (a) { vs. if (a)
|
||||||
|
# b(); b();
|
||||||
|
# } else { else if (c)
|
||||||
|
# if (c) { d();
|
||||||
|
# d(); else
|
||||||
|
# } else { e();
|
||||||
|
# e();
|
||||||
|
# }
|
||||||
|
# }
|
||||||
|
RemoveBracesLLVM: true
|
||||||
|
|
||||||
|
# Never v.s. Always
|
||||||
|
# #include <cstring> #include <cstring>
|
||||||
|
# struct Foo {
|
||||||
|
# int a, b, c; struct Foo {
|
||||||
|
# }; int a, b, c;
|
||||||
|
# namespace Ns { };
|
||||||
|
# class Bar {
|
||||||
|
# public: namespace Ns {
|
||||||
|
# struct Foobar { class Bar {
|
||||||
|
# int a; public:
|
||||||
|
# int b; struct Foobar {
|
||||||
|
# }; int a;
|
||||||
|
# private: int b;
|
||||||
|
# int t; };
|
||||||
|
# int method1() {
|
||||||
|
# // ... private:
|
||||||
|
# } int t;
|
||||||
|
# enum List {
|
||||||
|
# ITEM1, int method1() {
|
||||||
|
# ITEM2 // ...
|
||||||
|
# }; }
|
||||||
|
# template<typename T>
|
||||||
|
# int method2(T x) { enum List {
|
||||||
|
# // ... ITEM1,
|
||||||
|
# } ITEM2
|
||||||
|
# int i, j, k; };
|
||||||
|
# int method3(int par) {
|
||||||
|
# // ... template<typename T>
|
||||||
|
# } int method2(T x) {
|
||||||
|
# }; // ...
|
||||||
|
# class C {}; }
|
||||||
|
# }
|
||||||
|
# int i, j, k;
|
||||||
|
#
|
||||||
|
# int method3(int par) {
|
||||||
|
# // ...
|
||||||
|
# }
|
||||||
|
# };
|
||||||
|
#
|
||||||
|
# class C {};
|
||||||
|
# }
|
||||||
|
SeparateDefinitionBlocks: Always
|
||||||
|
|
||||||
|
# true: false:
|
||||||
|
# int a = 5; vs. int a= 5;
|
||||||
|
# a += 42; a+= 42;
|
||||||
|
SpaceBeforeAssignmentOperators: true
|
||||||
|
|
||||||
|
# Put a space before opening parentheses only after control statement keywords
|
||||||
|
# (for/if/while...).
|
||||||
|
#
|
||||||
|
# void f() {
|
||||||
|
# if (true) {
|
||||||
|
# f();
|
||||||
|
# }
|
||||||
|
# }
|
||||||
|
SpaceBeforeParens: ControlStatements
|
||||||
|
SpacesBeforeTrailingComments: 1
|
||||||
|
|
||||||
|
# static_cast<int>(arg);
|
||||||
|
# std::function<void(int)> fct;
|
||||||
|
SpacesInAngles: Never
|
||||||
|
|
||||||
|
Standard: Auto
|
||||||
|
|
||||||
|
# Macros which are ignored in front of a statement, as if they were an
|
||||||
|
# attribute. So that they are not parsed as identifier, for example for Qts
|
||||||
|
# emit.
|
||||||
|
# unsigned char data = 'x';
|
||||||
|
# emit signal(data); // This is parsed as variable declaration.
|
||||||
|
#
|
||||||
|
# vs.
|
||||||
|
#
|
||||||
|
# unsigned char data = 'x';
|
||||||
|
# emit signal(data); // Now it's fine again.
|
||||||
|
StatementAttributeLikeMacros: [emit]
|
||||||
|
---
|
377
Internal/os_nvim_init.vim
Normal file
377
Internal/os_nvim_init.vim
Normal file
@ -0,0 +1,377 @@
|
|||||||
|
" Plugins
|
||||||
|
" ==============================================================================
|
||||||
|
call plug#begin(stdpath('config') . '/plugged')
|
||||||
|
" nerdtree provides a file tree explorer
|
||||||
|
" vim-dispatch allows running async jobs in vim (i.e. builds in the background)
|
||||||
|
Plug 'https://github.com/scrooloose/nerdtree', { 'on': 'NERDTreeToggle' }
|
||||||
|
Plug 'https://github.com/tpope/vim-dispatch'
|
||||||
|
Plug 'https://github.com/tpope/vim-fugitive'
|
||||||
|
Plug 'https://github.com/tpope/vim-abolish'
|
||||||
|
|
||||||
|
" TODO: 2022-06-19 Treesitter is too slow on large C++ files
|
||||||
|
" Plug 'https://github.com/nvim-treesitter/nvim-treesitter', {'do': ':TSUpdate'}
|
||||||
|
Plug 'https://github.com/bfrg/vim-cpp-modern'
|
||||||
|
|
||||||
|
" FZF
|
||||||
|
Plug 'junegunn/fzf'
|
||||||
|
Plug 'junegunn/fzf.vim'
|
||||||
|
|
||||||
|
" FZF for LSP
|
||||||
|
Plug 'gfanto/fzf-lsp.nvim'
|
||||||
|
Plug 'nvim-lua/plenary.nvim'
|
||||||
|
|
||||||
|
" odin for syntax highlighting
|
||||||
|
Plug 'https://github.com/Tetralux/odin.vim'
|
||||||
|
Plug 'https://github.com/sainnhe/gruvbox-material'
|
||||||
|
|
||||||
|
" Lua cache to speed up load times
|
||||||
|
Plug 'https://github.com/lewis6991/impatient.nvim'
|
||||||
|
|
||||||
|
" lsp-zero begin
|
||||||
|
" LSP Support
|
||||||
|
Plug 'neovim/nvim-lspconfig'
|
||||||
|
Plug 'williamboman/mason.nvim'
|
||||||
|
Plug 'williamboman/mason-lspconfig.nvim'
|
||||||
|
|
||||||
|
" Autocompletion
|
||||||
|
Plug 'hrsh7th/nvim-cmp'
|
||||||
|
Plug 'hrsh7th/cmp-buffer'
|
||||||
|
Plug 'hrsh7th/cmp-path'
|
||||||
|
Plug 'saadparwaiz1/cmp_luasnip'
|
||||||
|
Plug 'hrsh7th/cmp-nvim-lsp'
|
||||||
|
Plug 'hrsh7th/cmp-nvim-lua'
|
||||||
|
|
||||||
|
" Snippets
|
||||||
|
Plug 'L3MON4D3/LuaSnip'
|
||||||
|
|
||||||
|
" Snippet collection (Optional)
|
||||||
|
Plug 'rafamadriz/friendly-snippets'
|
||||||
|
Plug 'VonHeikemen/lsp-zero.nvim'
|
||||||
|
" lsp-zero end
|
||||||
|
call plug#end()
|
||||||
|
|
||||||
|
" Lua Setup
|
||||||
|
" ==============================================================================
|
||||||
|
lua <<EOF
|
||||||
|
require('impatient')
|
||||||
|
|
||||||
|
-- LSP Setup
|
||||||
|
-- ===========================================================================
|
||||||
|
local lsp = require('lsp-zero')
|
||||||
|
lsp.preset('recommended')
|
||||||
|
lsp.setup()
|
||||||
|
|
||||||
|
-- Treesitter
|
||||||
|
-- ===========================================================================
|
||||||
|
-- TODO: 2022-06-19 Treesitter is too slow on large C++ files
|
||||||
|
-- require('nvim-treesitter.configs').setup {
|
||||||
|
-- ensure_installed = { "c", "cpp" }, -- A list of parser names, or "all"
|
||||||
|
-- sync_install = false, -- Install parsers synchronously (only applied to `ensure_installed`)
|
||||||
|
-- ignore_install = { }, -- List of parsers to ignore installing (for "all")
|
||||||
|
|
||||||
|
-- highlight = {
|
||||||
|
-- enable = false, -- `false` will disable the whole extension
|
||||||
|
|
||||||
|
-- -- NOTE: these are the names of the parsers and not the filetype. (for example if you want to
|
||||||
|
-- -- disable highlighting for the `tex` filetype, you need to include `latex` in this list as this is
|
||||||
|
-- -- the name of the parser)
|
||||||
|
-- -- list of language that will be disabled
|
||||||
|
-- disable = { },
|
||||||
|
|
||||||
|
-- -- Setting this to true will run `:h syntax` and tree-sitter at the same time.
|
||||||
|
-- -- Set this to `true` if you depend on 'syntax' being enabled (like for indentation).
|
||||||
|
-- -- Using this option may slow down your editor, and you may see some duplicate highlights.
|
||||||
|
-- -- Instead of true it can also be a list of languages
|
||||||
|
-- additional_vim_regex_highlighting = false,
|
||||||
|
-- },
|
||||||
|
-- }
|
||||||
|
|
||||||
|
-- Vim Options
|
||||||
|
-- ===========================================================================
|
||||||
|
vim.opt.autowrite=true -- Automatically save before cmds like :next and :prev
|
||||||
|
vim.opt.colorcolumn={80, 100} -- Set a 80 and 100 char column ruler
|
||||||
|
vim.opt.completeopt={'menu', 'menuone', 'noselect'}
|
||||||
|
vim.opt.cpoptions:append('$') -- $ as end marker for the change operator
|
||||||
|
vim.opt.cursorline=true -- Highlight current line
|
||||||
|
vim.opt.expandtab=true -- Replace tabs with spaces
|
||||||
|
vim.opt.guifont={'JetBrains_Mono:h9',
|
||||||
|
'Consolas:h9',
|
||||||
|
'InputMonoCondensed:h9'}
|
||||||
|
vim.opt.hlsearch=false -- Highlight just the first match on search
|
||||||
|
vim.opt.ignorecase=true -- Search is not case sensitive
|
||||||
|
vim.opt.linebreak=true -- On wrapped lines, break on the wrapping word intelligently
|
||||||
|
vim.opt.list=true -- Show the 'listchar' characters on trailing spaces, tabs e.t.c
|
||||||
|
vim.opt.listchars:append('tab:>-,trail:■,extends:»,precedes:«')
|
||||||
|
vim.opt.number=true -- Show line numbers
|
||||||
|
vim.opt.relativenumber=true -- Show relative line numbers
|
||||||
|
vim.opt.shiftwidth=4 -- Number of spaces for each autoindent step
|
||||||
|
vim.opt.splitright=true -- Open new splits to the right of the current one
|
||||||
|
vim.opt.swapfile=false -- Disable swapfile (stores the things changed in a file)
|
||||||
|
vim.opt.textwidth=80 -- On format, format to 80 char long lines
|
||||||
|
vim.opt.visualbell=true -- Flash the screen on error
|
||||||
|
vim.opt.wrap=false -- Don't wrap lines of text automatically
|
||||||
|
vim.opt.signcolumn = 'no'
|
||||||
|
|
||||||
|
vim.diagnostic.config({
|
||||||
|
-- Turn off the diagnostics signs on the line number. In LSP mode, editing
|
||||||
|
-- a C++ buffer constantly toggles the sign column on and off as you change
|
||||||
|
-- modes which is very visually distracting.
|
||||||
|
signs = false,
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Check if there were args (i.e. opened file), non-empty buffer, or started in insert mode
|
||||||
|
if vim.fn.argc() == 0 or vim.fn.line2byte("$") ~= -1 and not opt.insertmode then
|
||||||
|
local ascii = {
|
||||||
|
"",
|
||||||
|
" Useful Bindings (Normal Mode)",
|
||||||
|
" --------------------------------------------------",
|
||||||
|
" <Ctrl+n> to open the file tree explorer",
|
||||||
|
" <Ctrl+i> clang format selected lines",
|
||||||
|
" <Ctrl+j> jump to next compilation error",
|
||||||
|
" <Ctrl+k> jump to prev compilation error",
|
||||||
|
" <cd> change working directory to current file",
|
||||||
|
" <\\s> split buffer vertically",
|
||||||
|
"",
|
||||||
|
" Abolish (Text Substitution in Normal Mode)",
|
||||||
|
" --------------------------------------------------",
|
||||||
|
" %S/facilit{y,ies}/building{,s}/g Convert facility->building, facilities->buildings",
|
||||||
|
" %S/action/sleep/g Convert action to sleep, (preserve case sensitivity ACTION->SLEEP, action->sleep) ",
|
||||||
|
"",
|
||||||
|
" FZF (Normal Mode)",
|
||||||
|
" --------------------------------------------------",
|
||||||
|
" <\\h> vim command history",
|
||||||
|
" <\\f> find files",
|
||||||
|
" <\\g> search for text (via ripgrep)",
|
||||||
|
" <\\tt> search for tag (global)",
|
||||||
|
" <\\tb> search for tag (buffer)",
|
||||||
|
" <\\cc> search for commit (global)",
|
||||||
|
" <\\cb> search for commit (buffer)",
|
||||||
|
" <\\b> search for buffer",
|
||||||
|
"",
|
||||||
|
" Autocompletion (nvim-cmp in Normal Mode)",
|
||||||
|
" --------------------------------------------------",
|
||||||
|
" <Enter> Confirms selection.",
|
||||||
|
" <Ctrl-y> Confirms selection.",
|
||||||
|
" <Up> Navigate to previous item on the list.",
|
||||||
|
" <Down> Navigate to the next item on the list.",
|
||||||
|
" <Ctrl-p> Navigate to previous item on the list.",
|
||||||
|
" <Ctrl-n> Navigate to the next item on the list.",
|
||||||
|
" <Ctrl-u> Scroll up in the item's documentation.",
|
||||||
|
" <Ctrl-f> Scroll down in the item's documentation.",
|
||||||
|
" <Ctrl-e> Toggles the completion.",
|
||||||
|
" <Ctrl-d> Go to the next placeholder in the snippet.",
|
||||||
|
" <Ctrl-b> Go to the previous placeholder in the snippet.",
|
||||||
|
" <Tab> Enables completion when the cursor is inside a word. If the completion menu is visible it will navigate to the next item in the list.",
|
||||||
|
" <Shift-Tab> When the completion menu is visible navigate to the previous item in the list.",
|
||||||
|
"",
|
||||||
|
" LSP Bindings (Normal Mode)",
|
||||||
|
" --------------------------------------------------",
|
||||||
|
" <Shift-K> Displays hover information about the symbol under the cursor in a floating window. See help vim.lsp.buf.hover().",
|
||||||
|
" gd Jumps to the definition of the symbol under the cursor. See help vim.lsp.buf.definition().",
|
||||||
|
" gD Jumps to the declaration of the symbol under the cursor. Some servers don't implement this feature. See help vim.lsp.buf.declaration().",
|
||||||
|
" gi Lists all the implementations for the symbol under the cursor in the quickfix window. See help vim.lsp.buf.implementation().",
|
||||||
|
" go Jumps to the definition of the type of the symbol under the cursor. See help vim.lsp.buf.type_definition().",
|
||||||
|
" gr Lists all the references to the symbol under the cursor in the quickfix window. See help vim.lsp.buf.references().",
|
||||||
|
" <Ctrl-k> Displays signature information about the symbol under the cursor in a floating window. See help vim.lsp.buf.signature_help(). If a mapping already exists for this key this function is not bound.",
|
||||||
|
" <F2> Renames all references to the symbol under the cursor. See help vim.lsp.buf.rename().",
|
||||||
|
" <F4> Selects a code action available at the current cursor position. See help vim.lsp.buf.code_action().",
|
||||||
|
" gl Show diagnostics in a floating window. See :help vim.diagnostic.open_float().",
|
||||||
|
" [d Move to the previous diagnostic in the current buffer. See :help vim.diagnostic.goto_prev().",
|
||||||
|
" ]d Move to the next diagnostic. See :help vim.diagnostic.goto_next()."
|
||||||
|
}
|
||||||
|
|
||||||
|
local height = vim.api.nvim_get_option("lines")
|
||||||
|
local width = vim.api.nvim_get_option("columns")
|
||||||
|
local ascii_rows = #ascii
|
||||||
|
local ascii_cols = #ascii[1]
|
||||||
|
local win = vim.api.nvim_get_current_win()
|
||||||
|
local buf = vim.api.nvim_create_buf(true, true)
|
||||||
|
|
||||||
|
local function reset_start_screen()
|
||||||
|
vim.cmd("enew")
|
||||||
|
local buf = vim.api.nvim_get_current_buf()
|
||||||
|
local win = vim.api.nvim_get_current_win()
|
||||||
|
vim.api.nvim_buf_set_option(buf, "modifiable", true)
|
||||||
|
vim.api.nvim_buf_set_option(buf, "buflisted", true)
|
||||||
|
vim.api.nvim_buf_set_option(buf, "buflisted", true)
|
||||||
|
end
|
||||||
|
|
||||||
|
vim.api.nvim_buf_set_lines(buf, 0, -1, false, ascii)
|
||||||
|
vim.api.nvim_buf_set_option(buf, "modified", false)
|
||||||
|
vim.api.nvim_buf_set_option(buf, "buflisted", false)
|
||||||
|
vim.api.nvim_buf_set_option(buf, "bufhidden", "wipe")
|
||||||
|
vim.api.nvim_buf_set_option(buf, "buftype", "nofile")
|
||||||
|
vim.api.nvim_buf_set_option(buf, "swapfile", false)
|
||||||
|
vim.api.nvim_set_current_buf(buf)
|
||||||
|
|
||||||
|
vim.api.nvim_create_autocmd("InsertEnter,WinEnter", {
|
||||||
|
pattern = "<buffer>",
|
||||||
|
callback = reset_start_screen,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
EOF
|
||||||
|
|
||||||
|
" Theme
|
||||||
|
" ==============================================================================
|
||||||
|
let g:gruvbox_material_background='hard'
|
||||||
|
let g:gruvbox_material_foreground='mix'
|
||||||
|
let g:gruvbox_material_disable_italic_comment=1
|
||||||
|
let g:gruvbox_material_enable_italic=0
|
||||||
|
let g:gruvbox_material_enable_bold=0
|
||||||
|
let g:gruvbox_material_diagnostic_virtual_text='colored'
|
||||||
|
let g:gruvbox_material_better_performance=1
|
||||||
|
colorscheme gruvbox-material
|
||||||
|
|
||||||
|
" Vim-cpp-modern customisation
|
||||||
|
" Disable function highlighting (affects both C and C++ files)
|
||||||
|
let g:cpp_function_highlight = 1
|
||||||
|
|
||||||
|
" Enable highlighting of C++11 attributes
|
||||||
|
let g:cpp_attributes_highlight = 1
|
||||||
|
|
||||||
|
" Highlight struct/class member variables (affects both C and C++ files)
|
||||||
|
let g:cpp_member_highlight = 0
|
||||||
|
|
||||||
|
" Put all standard C and C++ keywords under Vim's highlight group 'Statement'
|
||||||
|
" (affects both C and C++ files)
|
||||||
|
let g:cpp_simple_highlight = 1
|
||||||
|
|
||||||
|
" Options
|
||||||
|
" ==============================================================================
|
||||||
|
" Show EOL type and last modified timestamp, right after the filename
|
||||||
|
set statusline=%<%F%h%m%r\ [%{&ff}]\ (%{strftime(\"%H:%M\ %d/%m/%Y\",getftime(expand(\"%:p\")))})%=%l,%c%V\ %P
|
||||||
|
|
||||||
|
" Resize splits when the window is resized
|
||||||
|
au VimResized * :wincmd =
|
||||||
|
|
||||||
|
" File patterns to ignore in command line auto complete
|
||||||
|
set wildignore+=*.class,*.o
|
||||||
|
set wildignore+=*\\tmp\\*,*.swp,*.zip,*.exe,*.obj,*.vcxproj,*.pdb,*.idb
|
||||||
|
|
||||||
|
" Setup undo file
|
||||||
|
set undofile
|
||||||
|
let &undodir=stdpath('config') . '/undo'
|
||||||
|
|
||||||
|
" Setup backup directory
|
||||||
|
let &backupdir=stdpath('config') . '/backup'
|
||||||
|
|
||||||
|
" Enable mouse support
|
||||||
|
if has('mouse')
|
||||||
|
set mouse=a
|
||||||
|
endif
|
||||||
|
|
||||||
|
" Functions
|
||||||
|
" ==============================================================================
|
||||||
|
" Increase font size using (Ctrl+Up Arrow) or (Ctrl+Down Arrow) if we are using
|
||||||
|
" gvim Otherwise font size is determined in terminal
|
||||||
|
nnoremap <C-Up> :silent! let &guifont = substitute(
|
||||||
|
\ &guifont,
|
||||||
|
\ ':h\zs\d\+',
|
||||||
|
\ '\=eval(submatch(0)+1)',
|
||||||
|
\ 'g')<CR>
|
||||||
|
nnoremap <C-Down> :silent! let &guifont = substitute(
|
||||||
|
\ &guifont,
|
||||||
|
\ ':h\zs\d\+',
|
||||||
|
\ '\=eval(submatch(0)-1)',
|
||||||
|
\ 'g')<CR>
|
||||||
|
|
||||||
|
" Formatting options (see :h fo-table)
|
||||||
|
augroup persistent_settings
|
||||||
|
au!
|
||||||
|
au bufenter * :set formatoptions=q1j
|
||||||
|
augroup end
|
||||||
|
|
||||||
|
" FZF
|
||||||
|
" ==============================================================================
|
||||||
|
" Empty value to disable preview window altogether
|
||||||
|
let g:fzf_preview_window = []
|
||||||
|
|
||||||
|
" Prefix all commands with Fzf for discoverability
|
||||||
|
let g:fzf_command_prefix = 'Fzf'
|
||||||
|
|
||||||
|
" - down / up / left / right
|
||||||
|
let g:fzf_layout = { 'down': '40%' }
|
||||||
|
|
||||||
|
" Add "FzfCustomRG" command which reinitializes
|
||||||
|
function! RipgrepFzf(query, fullscreen)
|
||||||
|
let command_fmt = 'rg --column --line-number --no-heading --color=always --smart-case -- %s || true'
|
||||||
|
let initial_command = printf(command_fmt, shellescape(a:query))
|
||||||
|
let reload_command = printf(command_fmt, '{q}')
|
||||||
|
let spec = {'options': ['--phony', '--query', a:query, '--bind', 'change:reload:'.reload_command]}
|
||||||
|
call fzf#vim#grep(initial_command, 1, fzf#vim#with_preview(spec), a:fullscreen)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
command! -nargs=* -bang FzfCustomRG call RipgrepFzf(<q-args>, <bang>0)
|
||||||
|
|
||||||
|
" Augment the "FzfCustomFiles" command
|
||||||
|
command! -bang -nargs=? -complete=dir FzfCustomFiles
|
||||||
|
\ call fzf#vim#files(<q-args>, {'options': ['--layout=reverse', '--info=inline', '--preview', 'cat {}']}, <bang>0)
|
||||||
|
|
||||||
|
" General Key Bindings
|
||||||
|
" ==============================================================================
|
||||||
|
" Telescope Bindings
|
||||||
|
nnoremap <leader>h <cmd>FzfHistory<cr>
|
||||||
|
nnoremap <leader>f <cmd>FzfCustomFiles<cr>
|
||||||
|
nnoremap <leader>g <cmd>FzfCustomRG<cr>
|
||||||
|
nnoremap <leader>tt <cmd>FzfTags<cr>
|
||||||
|
nnoremap <leader>tb <cmd>FzfBTags<cr>
|
||||||
|
nnoremap <leader>cc <cmd>FzfCommits<cr>
|
||||||
|
nnoremap <leader>cb <cmd>FzfBCommits<cr>
|
||||||
|
nnoremap <leader>b <cmd>FzfBuffers<cr>
|
||||||
|
|
||||||
|
" Map Ctrl+HJKL to navigate buffer window
|
||||||
|
nmap <silent> <C-h> :wincmd h<CR>
|
||||||
|
nmap <silent> <C-j> :wincmd j<CR>
|
||||||
|
nmap <silent> <C-k> :wincmd k<CR>
|
||||||
|
nmap <silent> <C-l> :wincmd l<CR>
|
||||||
|
|
||||||
|
" Move by wrapped lines instead of line numbers
|
||||||
|
nnoremap j gj
|
||||||
|
nnoremap k gk
|
||||||
|
nnoremap gj j
|
||||||
|
nnoremap gk k
|
||||||
|
|
||||||
|
" Map NERDTree to Ctrl-N
|
||||||
|
map <C-n> :NERDTreeToggle<CR>
|
||||||
|
|
||||||
|
" Change to current buffer's directory
|
||||||
|
nmap cd :cd <C-R>=expand("%:p:h")<CR><CR>
|
||||||
|
|
||||||
|
" Buffer Splitting
|
||||||
|
nnoremap <leader>s :vs<CR>
|
||||||
|
|
||||||
|
" Go to next error
|
||||||
|
" Go to previous error
|
||||||
|
nnoremap <A-j> :cn<CR>
|
||||||
|
nnoremap <A-k> :cp<CR>
|
||||||
|
|
||||||
|
" Clang Format
|
||||||
|
" ==============================================================================
|
||||||
|
map <C-I> :py3file ~/clang-format.py<CR>
|
||||||
|
|
||||||
|
" Compiler Error Formats
|
||||||
|
" ==============================================================================
|
||||||
|
" Error message formats thanks to
|
||||||
|
" https://forums.handmadehero.org/index.php/forum?view=topic&catid=4&id=704#3982
|
||||||
|
set errorformat+=\\\ %#%f(%l\\\,%c):\ %m " MSVC: MSBuild
|
||||||
|
set errorformat+=\\\ %#%f(%l)\ :\ %#%t%[A-z]%#\ %m " MSVC: cl.exe
|
||||||
|
set errorformat+=\\\ %#%t%nxx:\ %m " MSVC: cl.exe, fatal errors is crudely implemented
|
||||||
|
set errorformat+=\\\ %#LINK\ :\ %m " MSVC: link.exe, can't find link library badly implemented
|
||||||
|
set errorformat+=\\\ %#%s\ :\ error\ %m " MSVC: link.exe, errors is badly implemented
|
||||||
|
set errorformat+=\\\ %#%s\ :\ fatal\ error\ %m " MSVC: link.exe, fatal errors is badly implemented
|
||||||
|
set errorformat+=\\\ %#%f(%l\\\,%c-%*[0-9]):\ %#%t%[A-z]%#\ %m " MSVC: HLSL fxc.exe
|
||||||
|
set errorformat+=%\\%%(CTIME%\\)%\\@=%m " ctime.exe -stats
|
||||||
|
|
||||||
|
" Vim Dispatch
|
||||||
|
" ==============================================================================
|
||||||
|
let s:running_windows = has("win16") || has("win32") || has("win64")
|
||||||
|
if s:running_windows
|
||||||
|
set makeprg=build
|
||||||
|
nnoremap <f5> :Make ./build.bat<cr>
|
||||||
|
else
|
||||||
|
" Set vim terminal to enter normal mode using escape like normal vim behaviour
|
||||||
|
tnoremap <Esc> <C-\><C-n>
|
||||||
|
nnoremap <f5> :Make ./build.sh<cr>
|
||||||
|
set makeprg=./build.sh
|
||||||
|
endif
|
735
devenver.py
Normal file
735
devenver.py
Normal file
@ -0,0 +1,735 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# DEVenver
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# A simple python script to download portable applications and install them by
|
||||||
|
# unzipping them to a structured directory tree.
|
||||||
|
|
||||||
|
import urllib.request
|
||||||
|
import urllib.parse
|
||||||
|
import pathlib
|
||||||
|
import os
|
||||||
|
import tempfile
|
||||||
|
import hashlib
|
||||||
|
import shutil
|
||||||
|
import subprocess
|
||||||
|
import pprint
|
||||||
|
import argparse
|
||||||
|
import json
|
||||||
|
import importlib
|
||||||
|
|
||||||
|
from string import Template
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
# Internal
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
DOWNLOAD_CHUNK_SIZE = 1 * 1024 * 1024 # 1 megabyte
|
||||||
|
IS_WINDOWS = os.name == "nt"
|
||||||
|
|
||||||
|
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
default_base_dir = script_dir
|
||||||
|
default_base_downloads_dir = os.path.join(default_base_dir, 'Downloads')
|
||||||
|
default_base_install_dir = os.path.join(default_base_dir, 'Install')
|
||||||
|
|
||||||
|
# Arguments
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
arg_parser = argparse.ArgumentParser()
|
||||||
|
arg_parser.add_argument('--downloads-dir',
|
||||||
|
help=f'Set the directory where downloaded files are cached (default: {default_base_downloads_dir})',
|
||||||
|
default=default_base_downloads_dir,
|
||||||
|
type=pathlib.Path)
|
||||||
|
|
||||||
|
arg_parser.add_argument('--install-dir',
|
||||||
|
help=f'Set the directory where downloaded files are installed (default: {default_base_install_dir})',
|
||||||
|
default=default_base_install_dir,
|
||||||
|
type=pathlib.Path)
|
||||||
|
|
||||||
|
arg_parser.add_argument('--manifest-file',
|
||||||
|
help=f'Python file that has a get_manifest() function returning a dictionary of applications to download & install (see manifest.py for starters)',
|
||||||
|
required=True,
|
||||||
|
type=pathlib.Path)
|
||||||
|
|
||||||
|
arg_parser.add_argument('--version',
|
||||||
|
action='version',
|
||||||
|
version='DEVenver v1')
|
||||||
|
|
||||||
|
|
||||||
|
args = arg_parser.parse_args()
|
||||||
|
|
||||||
|
base_downloads_dir = args.downloads_dir
|
||||||
|
base_install_dir = args.install_dir
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# This app list must always be installed, they provide the tools to install all
|
||||||
|
# other archives. Upon installation, we will collect the installation executable
|
||||||
|
# path and store them in global variables for the rest of the progam to use to
|
||||||
|
# unzip the files.
|
||||||
|
internal_app_list = []
|
||||||
|
|
||||||
|
internal_app_list.append({
|
||||||
|
'label': '7zip',
|
||||||
|
'manifests': [],
|
||||||
|
})
|
||||||
|
|
||||||
|
version = "920"
|
||||||
|
internal_app_list[-1]['manifests'].append({ # Download the bootstrap 7zip, this can be unzipped using shutils
|
||||||
|
'download_checksum': '2a3afe19c180f8373fa02ff00254d5394fec0349f5804e0ad2f6067854ff28ac',
|
||||||
|
'download_url': f'https://www.7-zip.org/a/7za{version}.zip',
|
||||||
|
'version': version,
|
||||||
|
'executables': [
|
||||||
|
{
|
||||||
|
'path': '7za.exe',
|
||||||
|
'symlink': [],
|
||||||
|
'add_to_devenv_path': False,
|
||||||
|
'checksum': 'c136b1467d669a725478a6110ebaaab3cb88a3d389dfa688e06173c066b76fcf'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'add_to_devenv_script': [],
|
||||||
|
})
|
||||||
|
|
||||||
|
version = "2201"
|
||||||
|
internal_app_list[-1]['manifests'].append({ # Download proper 7zip, extract this exe with the bootstrap 7zip
|
||||||
|
'download_checksum': 'b055fee85472921575071464a97a79540e489c1c3a14b9bdfbdbab60e17f36e4',
|
||||||
|
'download_url': f'https://www.7-zip.org/a/7z{version}-x64.exe',
|
||||||
|
'version': version,
|
||||||
|
'executables': [
|
||||||
|
{
|
||||||
|
'path': '7z.exe',
|
||||||
|
'symlink': [],
|
||||||
|
'add_to_devenv_path': True,
|
||||||
|
'checksum': '254cf6411d38903b2440819f7e0a847f0cfee7f8096cfad9e90fea62f42b0c23'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'add_to_devenv_script': [],
|
||||||
|
})
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
version = "1.5.2"
|
||||||
|
internal_app_list.append({
|
||||||
|
"label": "zstd",
|
||||||
|
"manifests": [
|
||||||
|
{
|
||||||
|
"download_checksum": "68897cd037ee5e44c6d36b4dbbd04f1cc4202f9037415a3251951b953a257a09",
|
||||||
|
"download_url": f"https://github.com/facebook/zstd/releases/download/v{version}/zstd-v{version}-win64.zip",
|
||||||
|
"version": version,
|
||||||
|
"executables": [
|
||||||
|
{
|
||||||
|
"path": "zstd.exe",
|
||||||
|
"symlink": [],
|
||||||
|
"add_to_devenv_path": True,
|
||||||
|
"checksum": "f14e78c0651851a670f508561d2c5d647da0ba08e6b73231f2e7539812bae311",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"add_to_devenv_script": [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# These variables are set once they are downloaded dynamically and installed
|
||||||
|
# from the internal app listing!
|
||||||
|
zstd_exe = ""
|
||||||
|
zip7_exe = ""
|
||||||
|
zip7_bootstrap_exe = ""
|
||||||
|
|
||||||
|
|
||||||
|
# Functions
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
def print_header(title):
|
||||||
|
line = f'> ' + title + ' ';
|
||||||
|
print(line.ljust(100, '-'))
|
||||||
|
|
||||||
|
def lprint(*args, level=0, **kwargs):
|
||||||
|
print(' ' + (' ' * 2 * level), *args, **kwargs)
|
||||||
|
|
||||||
|
def lexit(*args, level=0, **kwargs):
|
||||||
|
print(' ' + (' ' * 2 * level), *args, **kwargs)
|
||||||
|
exit()
|
||||||
|
|
||||||
|
def verify_file_sha256(file_path, checksum, label):
|
||||||
|
if os.path.isfile(file_path) == False:
|
||||||
|
exit(f'Cannot verify SHA256, path is not a file [path={file_path}]')
|
||||||
|
|
||||||
|
result = False
|
||||||
|
try:
|
||||||
|
file = open(file_path, 'r+b')
|
||||||
|
hasher = hashlib.sha256()
|
||||||
|
hasher.update(file.read())
|
||||||
|
derived_checksum = hasher.hexdigest()
|
||||||
|
result = derived_checksum == checksum
|
||||||
|
if result:
|
||||||
|
lprint(f'- {label} SHA256 is good: {checksum}', level=1)
|
||||||
|
else:
|
||||||
|
lprint(f'- {label} SHA256 mismatch', level=1)
|
||||||
|
lprint(f' Expect: {checksum}', level=1)
|
||||||
|
lprint(f' Actual: {derived_checksum}', level=1)
|
||||||
|
except PermissionError as exception:
|
||||||
|
lprint(f"- {label} cannot verify SHA256 due to permission error, skipping", level=1)
|
||||||
|
result = True
|
||||||
|
else:
|
||||||
|
file.close()
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
def download_file_at_url(url, download_path, download_checksum, label):
|
||||||
|
# Check if file already downloaded and hashes match
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
file_already_downloaded = False
|
||||||
|
if os.path.isfile(download_path):
|
||||||
|
lprint(f'- Cached archive found: {download_path}', level=1)
|
||||||
|
file_already_downloaded = verify_file_sha256(download_path, download_checksum, 'Cached archive')
|
||||||
|
else:
|
||||||
|
lprint(f'- Download to disk: {download_path}', level=1)
|
||||||
|
lprint(f' URL: {url}', level=1)
|
||||||
|
|
||||||
|
# Download the file from URL
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
if file_already_downloaded == False:
|
||||||
|
lprint('Initiating download request ...', level=1)
|
||||||
|
with urllib.request.urlopen(url) as response:
|
||||||
|
temp_file = tempfile.mkstemp(text=False)
|
||||||
|
temp_file_handle = temp_file[0]
|
||||||
|
temp_file_path = temp_file[1]
|
||||||
|
temp_file_io = os.fdopen(temp_file_handle, mode='w+b')
|
||||||
|
|
||||||
|
download_failed = False
|
||||||
|
try:
|
||||||
|
line = ''
|
||||||
|
total_download_size = int(response.getheader('Content-Length'))
|
||||||
|
bytes_downloaded = 0
|
||||||
|
while chunk := response.read(DOWNLOAD_CHUNK_SIZE):
|
||||||
|
bytes_written = temp_file_io.write(chunk)
|
||||||
|
bytes_downloaded += bytes_written
|
||||||
|
percent_downloaded = int(bytes_downloaded / total_download_size * 100)
|
||||||
|
|
||||||
|
lprint(' ' * len(line), end='\r', level=1)
|
||||||
|
line = f'Downloading {percent_downloaded:.2f}% ({bytes_downloaded}/{total_download_size})'
|
||||||
|
lprint(line, end='\r', level=1)
|
||||||
|
except Exception as exception:
|
||||||
|
download_failed = True
|
||||||
|
lprint(f'Download {label} from {url} failed, {exception}', level=1)
|
||||||
|
finally:
|
||||||
|
temp_file_io.close()
|
||||||
|
print()
|
||||||
|
|
||||||
|
if download_failed == True:
|
||||||
|
os.remove(temp_file_path)
|
||||||
|
exit()
|
||||||
|
|
||||||
|
os.rename(temp_file_path, download_path)
|
||||||
|
|
||||||
|
if file_already_downloaded == False:
|
||||||
|
if verify_file_sha256(download_path, download_checksum, 'Downloaded archive') == False:
|
||||||
|
exit()
|
||||||
|
|
||||||
|
class UnzipMethod(Enum):
|
||||||
|
SHUTILS = 0
|
||||||
|
ZIP7_BOOTSTRAP = 1
|
||||||
|
DEFAULT = 2
|
||||||
|
|
||||||
|
def get_exe_install_dir(install_dir, label, version_label):
|
||||||
|
result = pathlib.Path(install_dir, label.replace(' ', '_'), version_label)
|
||||||
|
return result
|
||||||
|
|
||||||
|
def get_exe_install_path(install_dir, label, version_label, exe_rel_path):
|
||||||
|
install_dir = get_exe_install_dir(install_dir, label, version_label)
|
||||||
|
result = pathlib.Path(install_dir, exe_rel_path)
|
||||||
|
return result
|
||||||
|
|
||||||
|
def get_exe_symlink_dir(install_dir):
|
||||||
|
result = pathlib.Path(install_dir, "Symlinks")
|
||||||
|
return result
|
||||||
|
|
||||||
|
def download_and_install_archive(download_url,
|
||||||
|
download_checksum,
|
||||||
|
exe_list,
|
||||||
|
version_label,
|
||||||
|
label,
|
||||||
|
unzip_method,
|
||||||
|
download_dir,
|
||||||
|
install_dir):
|
||||||
|
|
||||||
|
exe_install_dir = get_exe_install_dir(install_dir=install_dir,
|
||||||
|
label=label,
|
||||||
|
version_label=version_label)
|
||||||
|
|
||||||
|
# Evaluate if we have already installed the requested archive
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
exes_are_not_a_file = []
|
||||||
|
exes_missing = []
|
||||||
|
exes_present = []
|
||||||
|
for exe_dict in exe_list:
|
||||||
|
exe_path = get_exe_install_path(install_dir=install_dir,
|
||||||
|
label=label,
|
||||||
|
version_label=version_label,
|
||||||
|
exe_rel_path=exe_dict['path'])
|
||||||
|
|
||||||
|
if os.path.exists(exe_path) == True:
|
||||||
|
if os.path.isfile(exe_path) == True:
|
||||||
|
exes_present.append(exe_dict)
|
||||||
|
else:
|
||||||
|
exes_are_not_a_file.append(exe_dict)
|
||||||
|
else:
|
||||||
|
exes_missing.append(exe_dict)
|
||||||
|
|
||||||
|
# Executables not install yet, verify, download and install if possible
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
if len(exes_present) != len(exe_list):
|
||||||
|
|
||||||
|
# Check if any of the manifest files are not files
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
|
if len(exes_are_not_a_file) > 0: # Some item exists at the path but they are not files
|
||||||
|
lprint(f'- {label} is installed but some of the expected executables are not a file!', level=1)
|
||||||
|
for exe_dict in exes_are_not_a_file:
|
||||||
|
lprint(f' {exe_dict["path"]}', level=1)
|
||||||
|
lprint(f' Installation cannot proceed as unpacking would overwrite these paths', level=1)
|
||||||
|
return
|
||||||
|
|
||||||
|
# Check if any files are missing
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
|
# Some executables are missing, some are available, installation will
|
||||||
|
# trample over existing files, its not safe to unzip the archive as we may
|
||||||
|
# overwrite config files or some other files that have been modified by the
|
||||||
|
# program.
|
||||||
|
#
|
||||||
|
# Note that all files missing means we can assume that we haven't installed
|
||||||
|
# yet ..
|
||||||
|
if len(exes_missing) > 0 and len(exes_missing) != len(exe_list):
|
||||||
|
lprint(f'- {label} is installed but some of the expected executables are missing from the installation!', level=1)
|
||||||
|
for exe_dict in exes_are_not_a_file:
|
||||||
|
lprint(f' {exe_dict["path"]}', level=1)
|
||||||
|
lprint(f' Installation cannot proceed as unpacking could delete ', level=1)
|
||||||
|
return
|
||||||
|
|
||||||
|
assert(len(exes_missing) == len(exe_list))
|
||||||
|
assert(len(exes_present) == 0)
|
||||||
|
|
||||||
|
# Not installed yet, download and install
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
|
# Determine the file name we are downloading from the URL
|
||||||
|
download_url_parts = urllib.parse.urlparse(download_url)
|
||||||
|
download_name = pathlib.Path(urllib.parse.unquote(download_url_parts.path))
|
||||||
|
|
||||||
|
# The path to move the temp file to after successful download, e.g.
|
||||||
|
# download_dir = C:/Dev/Downloads/Wezterm-windows-{version}.zip
|
||||||
|
# download_name = Wezterm-windows-{version}.zip
|
||||||
|
download_path = pathlib.Path(download_dir, download_name.name)
|
||||||
|
|
||||||
|
# Download the archive at the URL
|
||||||
|
download_file_at_url(download_url, download_path, download_checksum, label)
|
||||||
|
|
||||||
|
# Install the archive by unpacking it
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
|
if unzip_method == UnzipMethod.SHUTILS:
|
||||||
|
lprint(f'- SHUtils unzip install {label} to: {exe_install_dir}', level=1)
|
||||||
|
shutil.unpack_archive(download_path, exe_install_dir, 'zip')
|
||||||
|
else:
|
||||||
|
command = ''
|
||||||
|
if unzip_method == UnzipMethod.ZIP7_BOOTSTRAP:
|
||||||
|
command = f'"{zip7_bootstrap_exe}" x -bd "{download_path}" -o"{exe_install_dir}"'
|
||||||
|
lprint(f'- 7z (bootstrap) unzip {label} to: {exe_install_dir}', level=1)
|
||||||
|
lprint(f' Command: {command}', level=1)
|
||||||
|
subprocess.run(command)
|
||||||
|
else:
|
||||||
|
archive_path = download_path
|
||||||
|
intermediate_zip_file_extracted = False
|
||||||
|
|
||||||
|
# We could have a "app.zst" situation or an "app.tar.zst" situation
|
||||||
|
#
|
||||||
|
# "app.zst" only needs 1 extraction from the zstd tool
|
||||||
|
# "app.tar.zst" needs 1 zstd extract and then 1 7zip extract
|
||||||
|
#
|
||||||
|
# When we have "app.tar.zst" we extract to the install folder, e.g.
|
||||||
|
#
|
||||||
|
# "app/1.0/app.tar"
|
||||||
|
#
|
||||||
|
# We call this an intermediate zip file, we will extract that file
|
||||||
|
# with 7zip. After we're done, we will delete that _intermediate_
|
||||||
|
# file to cleanup our install directory.
|
||||||
|
if archive_path.suffix == '.zst':
|
||||||
|
|
||||||
|
archive_without_suffix = pathlib.Path(str(archive_path)[:-len(archive_path.suffix)]).name
|
||||||
|
next_archive_path = pathlib.Path(exe_install_dir, archive_without_suffix)
|
||||||
|
|
||||||
|
if os.path.exists(next_archive_path) == False:
|
||||||
|
command = f'"{zstd_exe}" --output-dir-flat "{exe_install_dir}" -d "{archive_path}"'
|
||||||
|
lprint(f'- zstd unzip {label} to: {exe_install_dir}', level=1)
|
||||||
|
lprint(f' Command: {command}', level=1)
|
||||||
|
|
||||||
|
os.makedirs(exe_install_dir)
|
||||||
|
subprocess.run(command)
|
||||||
|
|
||||||
|
# Remove the extension from the file, we just extracted it
|
||||||
|
archive_path = next_archive_path
|
||||||
|
|
||||||
|
# If there's still a suffix after we removed the ".zst" we got
|
||||||
|
# an additional archive to unzip, e.g. "app.tar" remaining.
|
||||||
|
intermediate_zip_file_extracted = len(archive_path.suffix) > 0
|
||||||
|
|
||||||
|
if len(archive_path.suffix) > 0:
|
||||||
|
command = f'"{zip7_exe}" x -aoa -spe -bso0 "{archive_path}" -o"{exe_install_dir}"'
|
||||||
|
command = command.replace('\\', '/')
|
||||||
|
lprint(f'- 7z unzip install {label} to: {exe_install_dir}', level=1)
|
||||||
|
lprint(f' Command: {command}', level=1)
|
||||||
|
subprocess.run(command)
|
||||||
|
|
||||||
|
if intermediate_zip_file_extracted:
|
||||||
|
lprint(f'- Detected intermediate zip file in install root, removing: {archive_path}', level=1)
|
||||||
|
os.remove(archive_path)
|
||||||
|
|
||||||
|
# Remove duplicate root folder if detected
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
|
# If after unpacking, there's only 1 directory in the install direction, we
|
||||||
|
# assume that the zip contains a root folder. We will automatically merge
|
||||||
|
# the root folder to the parent.
|
||||||
|
has_files_in_install_dir = False
|
||||||
|
dir_count = 0
|
||||||
|
dupe_root_folder_name = ''
|
||||||
|
with os.scandir(exe_install_dir) as scan_handle:
|
||||||
|
for it in list(scan_handle):
|
||||||
|
if it.is_file():
|
||||||
|
has_files_in_install_dir = True
|
||||||
|
break
|
||||||
|
elif it.is_dir():
|
||||||
|
dupe_root_folder_name = it.name
|
||||||
|
dir_count += 1
|
||||||
|
if dir_count > 1:
|
||||||
|
break
|
||||||
|
|
||||||
|
if dir_count == 1 and not has_files_in_install_dir:
|
||||||
|
# There is only one folder after we unzipped, what happened here is
|
||||||
|
# that the archive we unzipped had its contents within a root
|
||||||
|
# folder. We will pull those files out because we already unzipped
|
||||||
|
# into an isolated location for the application, e.g.
|
||||||
|
#
|
||||||
|
# Our install location C:/Dev/Install/7zip/920
|
||||||
|
# After unzip C:/Dev/Install/7zip/920/7zip-920-x64
|
||||||
|
#
|
||||||
|
# We have an duplicate '7zip-920-x64' directory in our
|
||||||
|
# installation. Move all the files in the duplicate directory up to
|
||||||
|
# our '920' folder then remove the duplicate folder.
|
||||||
|
dupe_root_folder_path = pathlib.Path(exe_install_dir, dupe_root_folder_name)
|
||||||
|
lprint(f'- Detected duplicate root folder after unzip: {dupe_root_folder_path}', level=1)
|
||||||
|
lprint(f' Merging duplicate root folder to parent: {exe_install_dir}', level=1)
|
||||||
|
for file_name in os.listdir(dupe_root_folder_path):
|
||||||
|
src = pathlib.Path(dupe_root_folder_path, file_name)
|
||||||
|
dest = pathlib.Path(exe_install_dir, file_name)
|
||||||
|
shutil.move(src, dest)
|
||||||
|
|
||||||
|
os.rmdir(dupe_root_folder_path)
|
||||||
|
|
||||||
|
# Verify the installation by checking the SHA256 of the executables
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
exes_with_bad_hashes = []
|
||||||
|
for exe_dict in exe_list:
|
||||||
|
exe_rel_path = exe_dict['path']
|
||||||
|
exe_path = get_exe_install_path(install_dir=install_dir,
|
||||||
|
label=label,
|
||||||
|
version_label=version_label,
|
||||||
|
exe_rel_path=exe_rel_path)
|
||||||
|
if os.path.isfile(exe_path) == False:
|
||||||
|
lexit(f'- Installed {label} but could not find expected file for validating install: {exe_path}', level=1)
|
||||||
|
|
||||||
|
if verify_file_sha256(file_path=exe_path, checksum=exe_dict['checksum'], label=exe_rel_path) == False:
|
||||||
|
exes_with_bad_hashes.append(exe_dict)
|
||||||
|
|
||||||
|
if len(exes_with_bad_hashes) > 0:
|
||||||
|
lprint(f'- {label} is installed but executable SHA256 does not match!', level=1)
|
||||||
|
lprint(f' See hashes above, executable path(s):', level=1)
|
||||||
|
for exe_dict in exes_with_bad_hashes:
|
||||||
|
lprint(f' {exe_dict["path"]}', level=1)
|
||||||
|
lprint(f' Something has modified the executable, this may be malicious or not!', level=1)
|
||||||
|
lprint(f' Manually uninstall the existing installation or amend the binary to be', level=1)
|
||||||
|
lprint(f' able to continue. Exiting.', level=1)
|
||||||
|
exit()
|
||||||
|
else:
|
||||||
|
lprint(f'- {label} installed and valid: {exe_install_dir}', level=1)
|
||||||
|
|
||||||
|
# Do the symlinks
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
symlink_dir = get_exe_symlink_dir(install_dir)
|
||||||
|
paths_to_add_to_devenv_script = set()
|
||||||
|
for exe_dict in exe_list:
|
||||||
|
exe_rel_path = exe_dict['path']
|
||||||
|
exe_path = get_exe_install_path(install_dir=install_dir,
|
||||||
|
label=label,
|
||||||
|
version_label=version_label,
|
||||||
|
exe_rel_path=exe_rel_path)
|
||||||
|
|
||||||
|
for symlink_entry in exe_dict["symlink"]:
|
||||||
|
symlink_dest = symlink_dir / symlink_entry
|
||||||
|
symlink_src = exe_path
|
||||||
|
if os.path.exists(symlink_dest):
|
||||||
|
# Windows uses hardlinks because symlinks require you to enable "developer" mode
|
||||||
|
# Everyone else uses symlinks
|
||||||
|
if (IS_WINDOWS and not os.path.isfile(symlink_dest)) or (not IS_WINDOWS and not os.path.islink(symlink_dest)):
|
||||||
|
lprint( "- Cannot create symlink! The destionation file to create the symlink at.", level=1)
|
||||||
|
lprint( " already exists and is *not* a link. We cannot remove this safely as we", level=1)
|
||||||
|
lprint( " don't know what it is, exiting.", level=1)
|
||||||
|
lprint(f" Symlink Source: {symlink_src}", level=1)
|
||||||
|
lexit (f" Symlink Dest: {symlink_dest}", level=1)
|
||||||
|
|
||||||
|
os.unlink(symlink_dest)
|
||||||
|
|
||||||
|
if IS_WINDOWS == True:
|
||||||
|
os.link(src=symlink_src, dst=symlink_dest)
|
||||||
|
else:
|
||||||
|
os.symlink(src=symlink_src, dst=symlink_dest)
|
||||||
|
|
||||||
|
# Collect paths to add to the devenv script
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
|
if exe_dict['add_to_devenv_path'] == True:
|
||||||
|
path = exe_path.parent.relative_to(install_dir)
|
||||||
|
paths_to_add_to_devenv_script.add(path)
|
||||||
|
|
||||||
|
global devenv_script_buffer
|
||||||
|
for path in paths_to_add_to_devenv_script:
|
||||||
|
if IS_WINDOWS:
|
||||||
|
devenv_script_buffer += f"set PATH=\"%~dp0{path}\";%PATH%\n"
|
||||||
|
else:
|
||||||
|
devenv_script_buffer += f"PATH=\"$( cd -- \"$( dirname -- \"${BASH_SOURCE[0]}\" )\" &> /dev/null && pwd ){path}\";%PATH%\n"
|
||||||
|
|
||||||
|
# Search the 2 dictionarries, 'first' and 'second' for the key. A matching key
|
||||||
|
# in 'first' taking precedence over the 'second' dictionary. If no key is
|
||||||
|
# found in either dictionaries then this function
|
||||||
|
# returns an empty string.
|
||||||
|
class ValidateAppListResult:
|
||||||
|
def __init__(self):
|
||||||
|
self.app_count = 0
|
||||||
|
|
||||||
|
def validate_app_list(app_list):
|
||||||
|
result = ValidateAppListResult()
|
||||||
|
manifest_rule_table = {
|
||||||
|
'download_checksum': 'manifest must specify the SHA256 checksum for the downloaded file',
|
||||||
|
'version': 'manifest must specify the app version that is to be installed',
|
||||||
|
'executables': 'manifest must specify an array of executable(s) for verifying installation',
|
||||||
|
'download_url': 'manifest must specify the URL to download the app from',
|
||||||
|
'add_to_devenv_script': 'manifest must specify an array of strings to inject into the portable development environment setup script',
|
||||||
|
}
|
||||||
|
|
||||||
|
executable_rule_table = {
|
||||||
|
'path': 'executables must specify a path to a file from the installation to verify its checksum',
|
||||||
|
'symlink': 'executables must specify an array of symlink names that will target the path',
|
||||||
|
'add_to_devenv_path': 'executables must specify an boolean to indicate if the executable path should be added to the environment path',
|
||||||
|
'checksum': 'executables must specify a string with the checksum of the executable',
|
||||||
|
}
|
||||||
|
|
||||||
|
for app in app_list:
|
||||||
|
manifest_list = app['manifests']
|
||||||
|
result.app_count += len(manifest_list)
|
||||||
|
|
||||||
|
# Verify the label
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
|
label = app.get('label', '')
|
||||||
|
if 'label' not in app:
|
||||||
|
exit('Label missing from application list, app must have a label specified, e.g. { "label": "App Name", "manifests": [] }')
|
||||||
|
|
||||||
|
# Verify that the mandatory keys are in the manifest
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
|
for manifest in manifest_list:
|
||||||
|
for key in manifest_rule_table:
|
||||||
|
value = manifest.get(key, "")
|
||||||
|
|
||||||
|
if key.startswith("add_to_devenv"):
|
||||||
|
if not isinstance(value, list):
|
||||||
|
exit(f'{label} error: {key} in manifest must be an array to proceed\n{pprint.pformat(app)}')
|
||||||
|
|
||||||
|
elif key == "executables":
|
||||||
|
for executable in value:
|
||||||
|
for executable_key in executable_rule_table:
|
||||||
|
executable_value = executable.get(executable_key, "")
|
||||||
|
|
||||||
|
if executable_key == "path":
|
||||||
|
if not isinstance(executable_value, str) or len(executable_value) == 0:
|
||||||
|
exit(f'{label} error: required key "{executable_key}" is invalid, {executable_rule_table[executable_key]}\n{pprint.pformat(app)}')
|
||||||
|
|
||||||
|
elif executable_key == "symlink":
|
||||||
|
if not isinstance(executable_value, list):
|
||||||
|
exit(f'{label} error: required key "{executable_key}" is invalid, {executable_rule_table[executable_key]}\n{pprint.pformat(app)}')
|
||||||
|
|
||||||
|
elif executable_key == "add_to_devenv_path":
|
||||||
|
if not isinstance(executable_value, bool):
|
||||||
|
exit(f'{label} error: required key "{executable_key}" is invalid, {executable_rule_table[executable_key]}\n{pprint.pformat(app)}')
|
||||||
|
|
||||||
|
elif executable_key == "checksum":
|
||||||
|
if not isinstance(executable_value, str):
|
||||||
|
exit(f'{label} error: required key "{executable_key}" is invalid, {executable_rule_table[executable_key]}\n{pprint.pformat(app)}')
|
||||||
|
|
||||||
|
elif len(value) == 0:
|
||||||
|
exit(f'{label} error: required key "{key}" is missing/empty, {manifest_rule_table[key]}\n{pprint.pformat(app)}')
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
devenv_script_buffer = """@echo off
|
||||||
|
|
||||||
|
"""
|
||||||
|
def install_app_list(app_list, download_dir, install_dir):
|
||||||
|
title = "Internal Apps" if app_list is internal_app_list else "User Apps"
|
||||||
|
print_header(title)
|
||||||
|
result = {}
|
||||||
|
|
||||||
|
validate_app_list_result = validate_app_list(app_list)
|
||||||
|
app_index = 0
|
||||||
|
|
||||||
|
for app in app_list:
|
||||||
|
manifest_list = app['manifests']
|
||||||
|
for manifest in manifest_list:
|
||||||
|
app_index += 1
|
||||||
|
|
||||||
|
# Extract variables from manifest
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
label = app["label"]
|
||||||
|
download_checksum = manifest['download_checksum']
|
||||||
|
version = manifest["version"]
|
||||||
|
download_url = manifest["download_url"]
|
||||||
|
exe_list = manifest['executables']
|
||||||
|
unzip_method = UnzipMethod.DEFAULT
|
||||||
|
|
||||||
|
# Bootstrapping code, when installing the internal app list, we will
|
||||||
|
# assign the variables to point to our unarchiving tools.
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
if app_list is internal_app_list:
|
||||||
|
global zip7_exe
|
||||||
|
global zip7_bootstrap_exe
|
||||||
|
global zstd_exe
|
||||||
|
exe_path = get_exe_install_path(install_dir, label, version, manifest['executables'][0]['path'])
|
||||||
|
if label == '7zip':
|
||||||
|
if version == '920':
|
||||||
|
unzip_method = UnzipMethod.SHUTILS
|
||||||
|
zip7_bootstrap_exe = exe_path
|
||||||
|
else:
|
||||||
|
unzip_method = UnzipMethod.ZIP7_BOOTSTRAP
|
||||||
|
zip7_exe = exe_path
|
||||||
|
|
||||||
|
if label == 'zstd':
|
||||||
|
zstd_exe = exe_path
|
||||||
|
|
||||||
|
|
||||||
|
# Download and install
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
lprint(f'[{app_index:03}/{validate_app_list_result.app_count:03}] Setup {label} v{version}', level=0)
|
||||||
|
download_and_install_archive(download_url=download_url,
|
||||||
|
download_checksum=download_checksum,
|
||||||
|
exe_list=exe_list,
|
||||||
|
version_label=version,
|
||||||
|
label=label,
|
||||||
|
unzip_method=unzip_method,
|
||||||
|
download_dir=download_dir,
|
||||||
|
install_dir=install_dir)
|
||||||
|
|
||||||
|
# Post-installation
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Collate results into results
|
||||||
|
if label not in result:
|
||||||
|
result.update({label: []})
|
||||||
|
|
||||||
|
for item in exe_list:
|
||||||
|
app_install_dir = get_exe_install_dir(install_dir, label, version)
|
||||||
|
app_exe_path = get_exe_install_path(install_dir, label, version, item['path'])
|
||||||
|
app_exe_dir = pathlib.Path(app_exe_path).parent
|
||||||
|
|
||||||
|
# Add executable into the result list
|
||||||
|
result[label].append({
|
||||||
|
'version': version,
|
||||||
|
'install_dir': app_install_dir,
|
||||||
|
'exe_path': app_exe_path,
|
||||||
|
})
|
||||||
|
|
||||||
|
# Add the snippets verbatim specified in the manifest
|
||||||
|
global devenv_script_buffer
|
||||||
|
for line in manifest['add_to_devenv_script']:
|
||||||
|
devenv_script_buffer += (line + '\n')
|
||||||
|
|
||||||
|
if app_list is internal_app_list:
|
||||||
|
if len(str(zip7_exe)) == 0 or len(str(zip7_bootstrap_exe)) == 0 or len(str(zstd_exe)) == 0:
|
||||||
|
exit("Internal app list did not install 7zip bootstrap, 7zip or zstd, we are unable to install archives\n"
|
||||||
|
f" - zip7_bootstrap_exe: {zip7_bootstrap_exe}\n"
|
||||||
|
f" - zip7_exe: {zip7_exe}\n"
|
||||||
|
f" - zstd_exe: {zstd_exe}\n")
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
def run(user_app_list,
|
||||||
|
download_dir=base_downloads_dir,
|
||||||
|
install_dir=base_install_dir):
|
||||||
|
""" Download and install the given user app list at the specified
|
||||||
|
directories. The apps given must be archives that can be unpacked for
|
||||||
|
installation (e.g. portable distributions).
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
user_app_list (list): A list of dictionaries that contain app and
|
||||||
|
manifest information dictating what is to be installed via this
|
||||||
|
function.
|
||||||
|
download_dir (string): The path that intermediate downloaded files will
|
||||||
|
be kept at.
|
||||||
|
install_dir (string): The path that installed applications will be
|
||||||
|
unpacked to
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
result (list): A list of dictionaries containing the install locations
|
||||||
|
of each app, e.g.
|
||||||
|
"""
|
||||||
|
# Run
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
# Create the starting directories and install the internal app list (e.g.
|
||||||
|
# 7zip) which will be used to unzip-install the rest of the apps in the user
|
||||||
|
# app list.
|
||||||
|
#
|
||||||
|
# To do this without dependencies, we first download an old version of 7zip,
|
||||||
|
# version 9.20 which is distributed as a .zip file which Python can natively
|
||||||
|
# unzip.
|
||||||
|
#
|
||||||
|
# We then use the old version of 7zip and download a newer version of 7zip
|
||||||
|
# and extract it using the bootstrap-ed version. As of writing this, 7zip
|
||||||
|
# does not release a portable distribution of itself yet, instead what we do
|
||||||
|
# is download the installer and extract it ourselves using the bootstrap
|
||||||
|
# 7zip.
|
||||||
|
|
||||||
|
# Create the paths requested by the user
|
||||||
|
os.makedirs(download_dir, exist_ok=True)
|
||||||
|
os.makedirs(install_dir, exist_ok=True)
|
||||||
|
os.makedirs(pathlib.Path(install_dir, "Symlinks"), exist_ok=True)
|
||||||
|
|
||||||
|
for path in [download_dir, install_dir]:
|
||||||
|
if not os.path.isdir(path):
|
||||||
|
exit(f'Path "{path}" is not a directory, script can not proceed. Exiting.')
|
||||||
|
|
||||||
|
# Validate all the manifests before starting
|
||||||
|
internal_app_validate_result = validate_app_list(internal_app_list)
|
||||||
|
user_app_validate_result = validate_app_list(user_app_list)
|
||||||
|
|
||||||
|
# Install apps
|
||||||
|
internal_apps = install_app_list(app_list=internal_app_list,
|
||||||
|
download_dir=download_dir,
|
||||||
|
install_dir=install_dir)
|
||||||
|
|
||||||
|
user_apps = install_app_list(app_list=user_app_list,
|
||||||
|
download_dir=download_dir,
|
||||||
|
install_dir=install_dir)
|
||||||
|
|
||||||
|
# Write the devenv script with environment variables
|
||||||
|
global devenv_script_buffer
|
||||||
|
devenv_script_buffer += "set PATH=\"%~dp0Symlinks\";%PATH%\n"
|
||||||
|
|
||||||
|
devenv_script_name = "devenv.bat" if IS_WINDOWS else "devenv.sh"
|
||||||
|
devenv_script_path = pathlib.Path(install_dir, devenv_script_name)
|
||||||
|
lprint(f"Writing script to augment the environment with installed applications: {devenv_script_path}")
|
||||||
|
with open(devenv_script_path, 'w') as file:
|
||||||
|
file.write(devenv_script_buffer)
|
||||||
|
|
||||||
|
# Merge the install dictionaries, this dictionary contains
|
||||||
|
# (app label) -> [array of installed versions]
|
||||||
|
result = internal_apps
|
||||||
|
for key, value in user_apps.items():
|
||||||
|
if key not in result:
|
||||||
|
result.update({key: value})
|
||||||
|
else:
|
||||||
|
result[key] += value
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
run()
|
976
devenver_manifest.py
Normal file
976
devenver_manifest.py
Normal file
@ -0,0 +1,976 @@
|
|||||||
|
def get_manifest():
|
||||||
|
result = []
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
version = "20221119-145034-49b9839f"
|
||||||
|
result.append({
|
||||||
|
"label": "WezTerm",
|
||||||
|
"manifests": [
|
||||||
|
{
|
||||||
|
"version": version,
|
||||||
|
"download_checksum": "7041d2c02d226c0c051cc9f6373d51ac9a2de00025e18582077c76e8ad68abe1",
|
||||||
|
"download_url": f"https://github.com/wez/wezterm/releases/download/{version}/WezTerm-windows-{version}.zip",
|
||||||
|
"executables": [
|
||||||
|
{
|
||||||
|
"path": "wezterm-gui.exe",
|
||||||
|
"symlink": [],
|
||||||
|
"add_to_devenv_path": True,
|
||||||
|
"checksum": "e3faa247d69a8a966302a2ab4e655b08b79548707db79a7b724cf18cccf5ae35",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"add_to_devenv_script": [],
|
||||||
|
}
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
version = "2.304"
|
||||||
|
result.append({
|
||||||
|
"label": "JetBrains_Mono_Font",
|
||||||
|
"manifests": [
|
||||||
|
{
|
||||||
|
"download_checksum": "6f6376c6ed2960ea8a963cd7387ec9d76e3f629125bc33d1fdcd7eb7012f7bbf",
|
||||||
|
"version": "2.304",
|
||||||
|
"download_url": f"https://download.jetbrains.com/fonts/JetBrainsMono-{version}.zip",
|
||||||
|
"executables": [
|
||||||
|
{
|
||||||
|
"path": "fonts/ttf/JetBrainsMono-Regular.ttf",
|
||||||
|
"symlink": [],
|
||||||
|
"add_to_devenv_path": False,
|
||||||
|
"checksum": "a0bf60ef0f83c5ed4d7a75d45838548b1f6873372dfac88f71804491898d138f",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"add_to_devenv_script": [],
|
||||||
|
}
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
result.append({
|
||||||
|
"label": "CMake",
|
||||||
|
"manifests": [],
|
||||||
|
})
|
||||||
|
|
||||||
|
version = "3.23.4"
|
||||||
|
result[-1]['manifests'].append({
|
||||||
|
"download_checksum": "df15113aaab9e5f8cac254e02cf23f70d02407c9bf2983c82a9fe0d35bd20682",
|
||||||
|
"download_url": f"https://github.com/Kitware/CMake/releases/download/v{version}/cmake-{version}-windows-x86_64.zip",
|
||||||
|
"version": "3.23.4",
|
||||||
|
"executables": [
|
||||||
|
{
|
||||||
|
"path": "bin/cmake.exe",
|
||||||
|
"symlink": [],
|
||||||
|
"add_to_devenv_path": True,
|
||||||
|
"checksum": "426074cd812586551fbab2bde67377113e2085c78c2e9a887748e85b4dc3dda5",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"add_to_devenv_script": [],
|
||||||
|
})
|
||||||
|
|
||||||
|
version = "3.10.3"
|
||||||
|
result[-1]['manifests'].append({
|
||||||
|
"download_checksum": "3bd57d1cfcf720a4cc72db77bda4c76a7b700fb0341821ad868963ad28856cd0",
|
||||||
|
"download_url": f"https://github.com/Kitware/CMake/releases/download/v{version}/cmake-{version}-win64-x64.zip",
|
||||||
|
"version": version,
|
||||||
|
"executables": [
|
||||||
|
{
|
||||||
|
"path": "bin/cmake.exe",
|
||||||
|
"symlink": [],
|
||||||
|
"add_to_devenv_path": False,
|
||||||
|
"checksum": "f2e3b486d87d2a6bc19b3a62c740028f3f8945875196ac7d3d0e69649e98730a",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"add_to_devenv_script": [],
|
||||||
|
})
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
version = "1.9.4"
|
||||||
|
result.append({
|
||||||
|
"label": "Doxygen",
|
||||||
|
"manifests": [
|
||||||
|
{
|
||||||
|
"download_checksum": "3b34098c5fb016baa1d29aba101fe9d6843213b966b92a6b12c8856c547ee0c4",
|
||||||
|
"download_url": f"https://github.com/doxygen/doxygen/releases/download/Release_{version.replace('.', '_')}/doxygen-{version}.windows.x64.bin.zip",
|
||||||
|
"version": version,
|
||||||
|
"executables": [
|
||||||
|
{
|
||||||
|
"path": "doxygen.exe",
|
||||||
|
"symlink": [f"doxygen-{version}.exe"],
|
||||||
|
"add_to_devenv_path": True,
|
||||||
|
"checksum": "3cb4d89f2b3db7eec2b6797dc6b49cdfe9adda954575898895260f66f312d730",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"add_to_devenv_script": [],
|
||||||
|
}
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
version = "2.39.1"
|
||||||
|
label = "Git"
|
||||||
|
result.append({
|
||||||
|
"label": f"{label}",
|
||||||
|
"manifests": [
|
||||||
|
{
|
||||||
|
"download_checksum": "b898306a44084b5fa13b9a52e06408d97234389d07ae41d9409bdf58cad3d227",
|
||||||
|
"download_url": f"https://github.com/git-for-windows/git/releases/download/v{version}.windows.1/PortableGit-{version}-64-bit.7z.exe",
|
||||||
|
"version": version,
|
||||||
|
"executables": [
|
||||||
|
{
|
||||||
|
"path": "cmd/git.exe",
|
||||||
|
"symlink": [],
|
||||||
|
"add_to_devenv_path": True,
|
||||||
|
"checksum": "2fc6d5be237efb6b429d8f40975f1a1cfe3bcac863d9335e24096c8b0ec38105",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"add_to_devenv_script": [
|
||||||
|
f"set PATH=\"%~dp0{label}\\{version}\\mingw64\\bin\";%PATH%",
|
||||||
|
f"set PATH=\"%~dp0{label}\\{version}\\usr\\bin\";%PATH%",
|
||||||
|
],
|
||||||
|
}
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
result.append({
|
||||||
|
"label": "GCC_MinGW_AArch64",
|
||||||
|
"manifests": [],
|
||||||
|
})
|
||||||
|
|
||||||
|
arch = "aarch64-none-elf"
|
||||||
|
version = "12.2.0"
|
||||||
|
|
||||||
|
result[-1]['manifests'].append({
|
||||||
|
"download_checksum": "729e8af6aecd85cce63435b94c310c01983091b5db54842cd6604298f29d047f",
|
||||||
|
"download_url": f"https://github.com/mmozeiko/build-gcc-arm/releases/download/gcc-v{version}/gcc-v{version}-{arch}.7z",
|
||||||
|
"version": version,
|
||||||
|
"executables": [
|
||||||
|
{
|
||||||
|
"path": f"bin/{arch}-g++.exe",
|
||||||
|
"checksum": "a26baffa86bc3401790d682f13f9b321ea56153eae7dd4f332bde40a6b76fcb3",
|
||||||
|
"symlink": [f"{arch}-g++-{version}.exe"],
|
||||||
|
"add_to_devenv_path": True,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": f"bin/{arch}-gcc.exe",
|
||||||
|
"checksum": "0f594c7e741207f1613aa958369b12fab781741718688710b7082cac172fadf5",
|
||||||
|
"symlink": [f"{arch}-gcc-{version}.exe"],
|
||||||
|
"add_to_devenv_path": True,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"add_to_devenv_script": [],
|
||||||
|
})
|
||||||
|
|
||||||
|
version = "11.3.0"
|
||||||
|
result[-1]['manifests'].append({
|
||||||
|
"download_checksum": "a000bdeeb225145a1450c1b9b1094ef71c13fc4de2ab300a65acbf51cd107c7d",
|
||||||
|
"download_url": f"https://github.com/mmozeiko/build-gcc-arm/releases/download/gcc-v{version}/gcc-v{version}-{arch}.7z",
|
||||||
|
"version": version,
|
||||||
|
"executables": [
|
||||||
|
{
|
||||||
|
"path": f"bin/{arch}-g++.exe",
|
||||||
|
"checksum": "47eaef0e603c9fcae18f2efada305888503e878053119ede3a9e0b8b8beac2ee",
|
||||||
|
"symlink": [f"{arch}-g++-{version}.exe"],
|
||||||
|
"add_to_devenv_path": False,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": f"bin/{arch}-gcc.exe",
|
||||||
|
"checksum": "205d0b05d64bc80908deb5a64e5f3bf8769cfc08b272835f97aaeaec13ccd533",
|
||||||
|
"symlink": [f"{arch}-gcc-{version}.exe"],
|
||||||
|
"add_to_devenv_path": False,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"add_to_devenv_script": [],
|
||||||
|
})
|
||||||
|
|
||||||
|
version = "10.3.0"
|
||||||
|
result[-1]['manifests'].append({
|
||||||
|
"download_checksum": "095ab5a12059fa5dc59f415c059eb577f443a766eb1dd312fbede0f59940f432",
|
||||||
|
"download_url": f"https://github.com/mmozeiko/build-gcc-arm/releases/download/gcc-v{version}/gcc-v{version}-{arch}.7z",
|
||||||
|
"version": version,
|
||||||
|
"executables": [
|
||||||
|
{
|
||||||
|
"path": f"bin/{arch}-g++.exe",
|
||||||
|
"checksum": "f2b2d3c6dab0f84a151835540f25e6d6f9442d00bf546bc4c709fad4b6fdda06",
|
||||||
|
"symlink": [f"{arch}-g++-{version}.exe"],
|
||||||
|
"add_to_devenv_path": False,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": f"bin/{arch}-gcc.exe",
|
||||||
|
"checksum": "95a8478ecb5133029f3058fb0207f19ee00157a6dd81f220e8308305f0e25fe8",
|
||||||
|
"symlink": [f"{arch}-gcc-{version}.exe"],
|
||||||
|
"add_to_devenv_path": False,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"add_to_devenv_script": [],
|
||||||
|
})
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
result.append({
|
||||||
|
"label": "GCC_MinGW_ARM",
|
||||||
|
"manifests": [],
|
||||||
|
})
|
||||||
|
|
||||||
|
arch = "arm-none-eabi"
|
||||||
|
version = "12.2.0"
|
||||||
|
result[-1]['manifests'].append({
|
||||||
|
"download_checksum": "aa581b3a5d446bb2d9827f2ea1f02b066b6713d4543d24abbd3181f626036c39",
|
||||||
|
"download_url": f"https://github.com/mmozeiko/build-gcc-arm/releases/download/gcc-v{version}/gcc-v{version}-{arch}.7z",
|
||||||
|
"version": version,
|
||||||
|
"executables": [
|
||||||
|
{
|
||||||
|
"path": f"bin/{arch}-g++.exe",
|
||||||
|
"checksum": "fa48985c43cf82b426c461381e4c50d0ac3e9425f7e97bf116e1bab4b3a2a388",
|
||||||
|
"symlink": [f"{arch}-g++-{version}.exe"],
|
||||||
|
"add_to_devenv_path": True,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": f"bin/{arch}-gcc.exe",
|
||||||
|
"checksum": "94a342aae99cae1a95f3636bb5c7b11f5e17015aee98b556989944ec38755be2",
|
||||||
|
"symlink": [f"{arch}-gcc-{version}.exe"],
|
||||||
|
"add_to_devenv_path": True,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"add_to_devenv_script": [],
|
||||||
|
})
|
||||||
|
|
||||||
|
version = "11.3.0"
|
||||||
|
result[-1]['manifests'].append({
|
||||||
|
"download_checksum": "797ed71f60fae386c8875bb4e75e244afb15ded9e00ac77b6670a62be7614cc6",
|
||||||
|
"download_url": f"https://github.com/mmozeiko/build-gcc-arm/releases/download/gcc-v{version}/gcc-v{version}-{arch}.7z",
|
||||||
|
"version": version,
|
||||||
|
"executables": [
|
||||||
|
{
|
||||||
|
"path": f"bin/{arch}-g++.exe",
|
||||||
|
"checksum": "a36f2ea6846badf7c91631f118e88967f25d6e479a9beea158445ce75403a655",
|
||||||
|
"symlink": [f"{arch}-g++-{version}.exe"],
|
||||||
|
"add_to_devenv_path": False,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": f"bin/{arch}-gcc.exe",
|
||||||
|
"checksum": "71158642a3d4921eda106a1b23640f1ed8bf1725ceaa98cbc8729a9a8115b09a",
|
||||||
|
"symlink": [f"{arch}-gcc-{version}.exe"],
|
||||||
|
"add_to_devenv_path": False,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"add_to_devenv_script": [],
|
||||||
|
})
|
||||||
|
|
||||||
|
version = "10.3.0"
|
||||||
|
result[-1]['manifests'].append({
|
||||||
|
"download_checksum": "af0fc2da062aa6423a91213e231ecc5981136b9b0655837ebdbbc5ad879d2d9e",
|
||||||
|
"download_url": f"https://github.com/mmozeiko/build-gcc-arm/releases/download/gcc-v{version}/gcc-v{version}-{arch}.7z",
|
||||||
|
"version": version,
|
||||||
|
"executables": [
|
||||||
|
{
|
||||||
|
"path": f"bin/{arch}-g++.exe",
|
||||||
|
"checksum": "c3dc49b561d177b3586992dfea86067eb8799e1586a7f26cea5b0ea97926632e",
|
||||||
|
"symlink": [f"{arch}-g++-{version}.exe"],
|
||||||
|
"add_to_devenv_path": False,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": f"bin/{arch}-gcc.exe",
|
||||||
|
"checksum": "7e680ffec593474a54193f5253b620cf59b6e3a1720dd35ab95bcb53582b7b7d",
|
||||||
|
"symlink": [f"{arch}-gcc-{version}.exe"],
|
||||||
|
"add_to_devenv_path": False,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"add_to_devenv_script": [],
|
||||||
|
})
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
result.append({
|
||||||
|
"label": "GCC_MinGW",
|
||||||
|
"manifests": [],
|
||||||
|
})
|
||||||
|
|
||||||
|
version = "12.2.0"
|
||||||
|
mingw_version = "10.0.0"
|
||||||
|
result[-1]['manifests'].append({
|
||||||
|
"download_checksum": "5cbe5ea7533f6d24af3a57fe7022032f420b15d7c4e38c0d16534a42d33213a4",
|
||||||
|
"download_url": f"https://github.com/mmozeiko/build-gcc/releases/download/gcc-v{version}-mingw-v{mingw_version}/gcc-v{version}-mingw-v{mingw_version}-x86_64.7z",
|
||||||
|
"version": version,
|
||||||
|
"executables": [
|
||||||
|
{
|
||||||
|
"path": f"bin/g++.exe",
|
||||||
|
"checksum": "886b0f25256ddbd0f4ad09e6e3b81279f9a8b6a1b5c32c714c9c201d802caa39",
|
||||||
|
"symlink": [f"g++-{version}.exe"],
|
||||||
|
"add_to_devenv_path": True,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": f"bin/gcc.exe",
|
||||||
|
"checksum": "91c910fa5257fdfd0291c347c81a73c7facb1f486dba941f977714672895c96e",
|
||||||
|
"symlink": [f"gcc-{version}.exe"],
|
||||||
|
"add_to_devenv_path": True,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"add_to_devenv_script": [],
|
||||||
|
})
|
||||||
|
|
||||||
|
version = "11.3.0"
|
||||||
|
result[-1]['manifests'].append({
|
||||||
|
"download_checksum": "e2c5c64659aeda77680c5eec80bbaa4db3f117b21febeb3f13fd76d580604fd0",
|
||||||
|
"download_url": f"https://github.com/mmozeiko/build-gcc/releases/download/gcc-v{version}-mingw-v{mingw_version}/gcc-v{version}-mingw-v{mingw_version}-x86_64.7z",
|
||||||
|
"version": version,
|
||||||
|
"executables": [
|
||||||
|
{
|
||||||
|
"path": f"bin/g++.exe",
|
||||||
|
"checksum": "e92ecfa0171f2ab0c3ca39f2121ab5e887b3a378399a4be7e056820f5841c7a5",
|
||||||
|
"symlink": [f"g++-{version}.exe"],
|
||||||
|
"add_to_devenv_path": False,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": f"bin/gcc.exe",
|
||||||
|
"checksum": "f3226120196ea37ab3e450bd0f26d816ee28556d18aa0de64c3e427f31d66eeb",
|
||||||
|
"symlink": [f"gcc-{version}.exe"],
|
||||||
|
"add_to_devenv_path": False,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"add_to_devenv_script": [],
|
||||||
|
})
|
||||||
|
|
||||||
|
version = "10.3.0"
|
||||||
|
mingw_version = "8.0.0"
|
||||||
|
result[-1]['manifests'].append({
|
||||||
|
"download_checksum": "c8f38f6b1d264d7e008009bd32a04ca71b4ee3a3113e67930ab31c2e06818317",
|
||||||
|
"download_url": f"https://github.com/mmozeiko/build-gcc/releases/download/gcc-v{version}-mingw-v{mingw_version}/gcc-v{version}-mingw-v{mingw_version}-x86_64.7z",
|
||||||
|
"version": version,
|
||||||
|
"executables": [
|
||||||
|
{
|
||||||
|
"path": f"bin/g++.exe",
|
||||||
|
"checksum": "5c93b6da129ea01ee5fc87d5c7db948fc3bc62bae261ded9a883f1fa543571d2",
|
||||||
|
"symlink": [f"g++-{version}.exe"],
|
||||||
|
"add_to_devenv_path": False,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": f"bin/gcc.exe",
|
||||||
|
"checksum": "54a5f8d09e6741b9c94d1494f383c424c20449e3e06f36bf96603aeda9874405",
|
||||||
|
"symlink": [f"gcc-{version}.exe"],
|
||||||
|
"add_to_devenv_path": False,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"add_to_devenv_script": [],
|
||||||
|
})
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
result.append({
|
||||||
|
"label": "LLVM",
|
||||||
|
"manifests": [],
|
||||||
|
})
|
||||||
|
|
||||||
|
version = "15.0.7"
|
||||||
|
result[-1]['manifests'].append({
|
||||||
|
"download_checksum": "5428cb72acf63ce3bc4328e546a36674c9736ec040ecc176d362201c6548e6a8",
|
||||||
|
"download_url": f"https://github.com/llvm/llvm-project/releases/download/llvmorg-{version}/LLVM-{version}-win64.exe",
|
||||||
|
"version": version,
|
||||||
|
"executables": [
|
||||||
|
{
|
||||||
|
"path": f"bin/clang++.exe",
|
||||||
|
"checksum": "1f523e33de4ce9d591b4eb9bad102f086e8480488148f8db0d5c87056798ce3e",
|
||||||
|
"symlink": [f"clang++-{version}.exe"],
|
||||||
|
"add_to_devenv_path": True,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": f"bin/clang.exe",
|
||||||
|
"checksum": "1f523e33de4ce9d591b4eb9bad102f086e8480488148f8db0d5c87056798ce3e",
|
||||||
|
"symlink": [f"clang-{version}.exe"],
|
||||||
|
"add_to_devenv_path": True,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"add_to_devenv_script": [],
|
||||||
|
})
|
||||||
|
|
||||||
|
version = "14.0.6"
|
||||||
|
result[-1]['manifests'].append({
|
||||||
|
"download_checksum": "e8dbb2f7de8e37915273d65c1c2f2d96844b96bb8e8035f62c5182475e80b9fc",
|
||||||
|
"download_url": f"https://github.com/llvm/llvm-project/releases/download/llvmorg-{version}/LLVM-{version}-win64.exe",
|
||||||
|
"version": version,
|
||||||
|
"executables": [
|
||||||
|
{
|
||||||
|
"path": f"bin/clang++.exe",
|
||||||
|
"checksum": "d557b79bc09a01141ac7d940016f52ce1db081e31d7968f0d9b6f4c192d8f8cc",
|
||||||
|
"symlink": [f"clang++-{version}.exe"],
|
||||||
|
"add_to_devenv_path": False,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": f"bin/clang.exe",
|
||||||
|
"checksum": "d557b79bc09a01141ac7d940016f52ce1db081e31d7968f0d9b6f4c192d8f8cc",
|
||||||
|
"symlink": [f"clang-{version}.exe"],
|
||||||
|
"add_to_devenv_path": False,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"add_to_devenv_script": [],
|
||||||
|
})
|
||||||
|
|
||||||
|
version = "13.0.1"
|
||||||
|
result[-1]['manifests'].append({
|
||||||
|
"download_checksum": "9d15be034d52ec57cfc97615634099604d88a54761649498daa7405983a7e12f",
|
||||||
|
"download_url": f"https://github.com/llvm/llvm-project/releases/download/llvmorg-{version}/LLVM-{version}-win64.exe",
|
||||||
|
"version": version,
|
||||||
|
"executables": [
|
||||||
|
{
|
||||||
|
"path": f"bin/clang++.exe",
|
||||||
|
"checksum": "e3f26820ac446cb7c471cce49f6646b4346aa5380d11790ceaa7bf494a94b21d",
|
||||||
|
"symlink": [f"clang++-{version}.exe"],
|
||||||
|
"add_to_devenv_path": False,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": f"bin/clang.exe",
|
||||||
|
"checksum": "e3f26820ac446cb7c471cce49f6646b4346aa5380d11790ceaa7bf494a94b21d",
|
||||||
|
"symlink": [f"clang-{version}.exe"],
|
||||||
|
"add_to_devenv_path": False,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"add_to_devenv_script": [],
|
||||||
|
})
|
||||||
|
|
||||||
|
version = "12.0.1"
|
||||||
|
result[-1]['manifests'].append({
|
||||||
|
"download_checksum": "fcbabc9a170208bb344f7bba8366cca57ff103d72a316781bbb77d634b9e9433",
|
||||||
|
"download_url": f"https://github.com/llvm/llvm-project/releases/download/llvmorg-{version}/LLVM-{version}-win64.exe",
|
||||||
|
"version": version,
|
||||||
|
"executables": [
|
||||||
|
{
|
||||||
|
"path": f"bin/clang++.exe",
|
||||||
|
"checksum": "9f0748de7f946c210a030452de226986bab46a0121d7236ea0e7b5079cb6dfef",
|
||||||
|
"symlink": [f"clang++-{version}.exe"],
|
||||||
|
"add_to_devenv_path": False,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": f"bin/clang.exe",
|
||||||
|
"checksum": "9f0748de7f946c210a030452de226986bab46a0121d7236ea0e7b5079cb6dfef",
|
||||||
|
"symlink": [f"clang-{version}.exe"],
|
||||||
|
"add_to_devenv_path": False,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"add_to_devenv_script": [],
|
||||||
|
})
|
||||||
|
|
||||||
|
version = "11.1.0"
|
||||||
|
result[-1]['manifests'].append({
|
||||||
|
"download_checksum": "b5770bbfac712d273938cd155e232afaa85c2e8d865c7ca504a104a838568516",
|
||||||
|
"download_url": f"https://github.com/llvm/llvm-project/releases/download/llvmorg-{version}/LLVM-{version}-win64.exe",
|
||||||
|
"version": version,
|
||||||
|
"executables": [
|
||||||
|
{
|
||||||
|
"path": f"bin/clang++.exe",
|
||||||
|
"checksum": "f72591f8a02e4b7573aa2fcd2999a3ea76fe729e2468e5414853617268798dfd",
|
||||||
|
"symlink": [f"clang++-{version}.exe"],
|
||||||
|
"add_to_devenv_path": False,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": f"bin/clang.exe",
|
||||||
|
"checksum": "f72591f8a02e4b7573aa2fcd2999a3ea76fe729e2468e5414853617268798dfd",
|
||||||
|
"symlink": [f"clang-{version}.exe"],
|
||||||
|
"add_to_devenv_path": False,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"add_to_devenv_script": [],
|
||||||
|
})
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
version = "1.11.1"
|
||||||
|
result.append({
|
||||||
|
"label": "Ninja",
|
||||||
|
"manifests": [
|
||||||
|
{
|
||||||
|
"download_url": f"https://github.com/ninja-build/ninja/releases/download/v{version}/ninja-win.zip",
|
||||||
|
"download_checksum": "524b344a1a9a55005eaf868d991e090ab8ce07fa109f1820d40e74642e289abc",
|
||||||
|
"version": version,
|
||||||
|
"executables": [
|
||||||
|
{
|
||||||
|
"path": "ninja.exe",
|
||||||
|
"symlink": [],
|
||||||
|
"add_to_devenv_path": True,
|
||||||
|
"checksum": "23e7d60c17b3fcd42d9c00d49eca3c3771b04d7ccb13e49836b06b34e20211c7",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"add_to_devenv_script": [],
|
||||||
|
}
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
version = "16.19.0"
|
||||||
|
result.append({
|
||||||
|
"label": "NodeJS",
|
||||||
|
"manifests": [
|
||||||
|
{
|
||||||
|
"download_checksum": "e07399a4a441091ca0a5506faf7a9236ea1675220146daeea3bee828c2cbda3f",
|
||||||
|
"download_url": f"https://nodejs.org/dist/v{version}/node-v{version}-win-x64.7z",
|
||||||
|
"version": version,
|
||||||
|
"executables": [
|
||||||
|
{
|
||||||
|
"path": "node.exe",
|
||||||
|
"symlink": [f"node-{version}.exe"],
|
||||||
|
"add_to_devenv_path": True,
|
||||||
|
"checksum": "e4e7f389fbec9300275defc749246c62bdbe4f66406eb01e7c9a4101e07352da",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"add_to_devenv_script": [],
|
||||||
|
}
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
date = "20230116"
|
||||||
|
version = f"3.10.9+{date}"
|
||||||
|
label = "Python"
|
||||||
|
result.append({
|
||||||
|
"label": f"{label}",
|
||||||
|
"manifests": [
|
||||||
|
{
|
||||||
|
"download_checksum": "4cfa6299a78a3959102c461d126e4869616f0a49c60b44220c000fc9aecddd78",
|
||||||
|
"download_url": f"https://github.com/indygreg/python-build-standalone/releases/download/{date}/cpython-{version}-x86_64-pc-windows-msvc-shared-pgo-full.tar.zst",
|
||||||
|
"version": version,
|
||||||
|
"executables": [
|
||||||
|
{
|
||||||
|
"path": "install/python.exe",
|
||||||
|
"symlink": [],
|
||||||
|
"add_to_devenv_path": True,
|
||||||
|
"checksum": "6dafb845aba67aba898f5aa8adf6c48061e7ffea1d2ed7d290a1e4386e78f2f0",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"add_to_devenv_script": [
|
||||||
|
f"set PYTHONHOME=%~dp0{label}\\{version}\\install",
|
||||||
|
f"set PATH=\"%~dp0{label}\\{version}\\install\\Script\";%PATH%",
|
||||||
|
],
|
||||||
|
}
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
version = "1.24"
|
||||||
|
result.append({
|
||||||
|
"label": "Renderdoc",
|
||||||
|
"manifests": [
|
||||||
|
{
|
||||||
|
"download_url": f"https://renderdoc.org/stable/{version}/RenderDoc_{version}_64.zip",
|
||||||
|
"download_checksum": "dbd215f7e1c7933b8eedc49499a4372c92e68ddab04af4658f434bfe6c382a9a",
|
||||||
|
"version": version,
|
||||||
|
"executables": [
|
||||||
|
{
|
||||||
|
"path": "qrenderdoc.exe",
|
||||||
|
"symlink": [],
|
||||||
|
"add_to_devenv_path": False,
|
||||||
|
"checksum": "cfb96468355a416568faf89db18cd8a195bccec87ea16b3fffd3cc13c952c5fd",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"add_to_devenv_script": [],
|
||||||
|
}
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
version = "0.6.1"
|
||||||
|
result.append({
|
||||||
|
"label": "Zeal",
|
||||||
|
"manifests": [
|
||||||
|
{
|
||||||
|
"download_url": f"https://github.com/zealdocs/zeal/releases/download/v{version}/zeal-portable-{version}-windows-x64.7z",
|
||||||
|
"download_checksum": "08e9992f620ba0a5ea348471d8ac9c85059e95eedd950118928be639746e3f94",
|
||||||
|
"version": version,
|
||||||
|
"executables": [
|
||||||
|
{
|
||||||
|
"path": "zeal.exe",
|
||||||
|
"symlink": [],
|
||||||
|
"add_to_devenv_path": False,
|
||||||
|
"checksum": "d1e687a33e117b6319210f40e2401b4a68ffeb0f33ef82f5fb6a31ce4514a423",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"add_to_devenv_script": [],
|
||||||
|
}
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
version = "0.10.1"
|
||||||
|
result.append({
|
||||||
|
"label": "Zig",
|
||||||
|
"manifests": [
|
||||||
|
{
|
||||||
|
"download_url": f"https://ziglang.org/download/{version}/zig-windows-x86_64-{version}.zip",
|
||||||
|
"download_checksum": "5768004e5e274c7969c3892e891596e51c5df2b422d798865471e05049988125",
|
||||||
|
"version": version,
|
||||||
|
"executables": [
|
||||||
|
{
|
||||||
|
"path": "zig.exe",
|
||||||
|
"symlink": [f"zig-{version}.exe"],
|
||||||
|
"add_to_devenv_path": True,
|
||||||
|
"checksum": "607c9928a24f9d2e08df1ee240ebfd15ab1eb3c14b85e02f7dad6f8c8b53fea8",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"add_to_devenv_script": [],
|
||||||
|
}
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
version = "1.4.13"
|
||||||
|
git_hash = "0066c6"
|
||||||
|
result.append({
|
||||||
|
"label": "clink",
|
||||||
|
"manifests": [
|
||||||
|
{
|
||||||
|
"download_url": f"https://github.com/chrisant996/clink/releases/download/v{version}/clink.{version}.{git_hash}.zip",
|
||||||
|
"download_checksum": "800f7657d73a00dad40d46c9317bd418172ee40cc8b3958e32fba1f0b596e829",
|
||||||
|
"version": version,
|
||||||
|
"executables": [
|
||||||
|
{
|
||||||
|
"path": "clink_x64.exe",
|
||||||
|
"symlink": [],
|
||||||
|
"add_to_devenv_path": False,
|
||||||
|
"checksum": "331266334f59f2c978ff8e13bbcadb218051e790b61d9cc69e85617276c51298",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"add_to_devenv_script": [
|
||||||
|
"set CLINK_PATH=%~dp0clink-completions"
|
||||||
|
],
|
||||||
|
}
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
version = "1.11.1"
|
||||||
|
result.append({
|
||||||
|
"label": "Dependencies",
|
||||||
|
"manifests": [
|
||||||
|
{
|
||||||
|
"download_url": f"https://github.com/lucasg/Dependencies/releases/download/v{version}/Dependencies_x64_Release.zip",
|
||||||
|
"download_checksum": "7d22dc00f1c09fd4415d48ad74d1cf801893e83b9a39944b0fce6dea7ceaea99",
|
||||||
|
"version": version,
|
||||||
|
"executables": [
|
||||||
|
{
|
||||||
|
"path": "DependenciesGui.exe",
|
||||||
|
"symlink": [],
|
||||||
|
"add_to_devenv_path": False,
|
||||||
|
"checksum": "1737e5406128c3560bbb2bced3ac62d77998e592444f94b10cc0aa0bb1e617e6",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"add_to_devenv_script": [],
|
||||||
|
}
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
version = "1.4.1.1022"
|
||||||
|
result.append({
|
||||||
|
"label": "Everything",
|
||||||
|
"manifests": [
|
||||||
|
{
|
||||||
|
"download_url": f"https://www.voidtools.com/Everything-{version}.x64.zip",
|
||||||
|
"download_checksum": "c718bcd73d341e64c8cb47e97eb0c45d010fdcc45c2488d4a3a3c51acc775889",
|
||||||
|
"version": version,
|
||||||
|
"executables": [
|
||||||
|
{
|
||||||
|
"path": "Everything.exe",
|
||||||
|
"symlink": [],
|
||||||
|
"add_to_devenv_path": False,
|
||||||
|
"checksum": "9c282a47a18477af505e64b45c3609f21f13fe1f6ff289065497a1ec00f5d332",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"add_to_devenv_script": [],
|
||||||
|
}
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
version = "0.37.0"
|
||||||
|
result.append({
|
||||||
|
"label": "fzf",
|
||||||
|
"manifests": [
|
||||||
|
{
|
||||||
|
"download_url": f"https://github.com/junegunn/fzf/releases/download/{version}/fzf-{version}-windows_amd64.zip",
|
||||||
|
"download_checksum": "247bffe84ff3294a8c0a7bb96329d5e4152d3d034e13dec59dcc97d8a828000d",
|
||||||
|
"version": version,
|
||||||
|
"executables": [
|
||||||
|
{
|
||||||
|
"path": "fzf.exe",
|
||||||
|
"symlink": [],
|
||||||
|
"add_to_devenv_path": True,
|
||||||
|
"checksum": "c0f4b20d0602977ff3e592cac8eadf86473abed0d24e2def81239bd2e76047e8",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"add_to_devenv_script": [],
|
||||||
|
}
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
version = "1.1.41.1"
|
||||||
|
result.append({
|
||||||
|
"label": "jpegview",
|
||||||
|
"manifests": [
|
||||||
|
{
|
||||||
|
"download_url": f"https://github.com/sylikc/jpegview/releases/download/v{version}/JPEGView_{version}.7z",
|
||||||
|
"download_checksum": "7dd4b4b34b14e5fae331c7f4ebfb658be6684c70ec055cb1964642a8b45e4886",
|
||||||
|
"version": version,
|
||||||
|
"executables": [
|
||||||
|
{
|
||||||
|
"path": "JPEGView64/JPEGView.exe",
|
||||||
|
"symlink": [],
|
||||||
|
"add_to_devenv_path": False,
|
||||||
|
"checksum": "f4fe2308c932a5f4f41f67b0520fe1fe8a96c94169d98c83f9501e9dc84b56ad",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"add_to_devenv_script": [],
|
||||||
|
}
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
version = "22.02"
|
||||||
|
result.append({
|
||||||
|
"label": "mpc-qt",
|
||||||
|
"manifests": [
|
||||||
|
{
|
||||||
|
"download_url": f"https://github.com/sylikc/jpegview/releases/download/v{version}/JPEGView_{version}.7z",
|
||||||
|
"download_checksum": "2230c4f4de1a429ccc67e5c590efc0a86fbaffeb33a4dc5f391aa45e660b80c2",
|
||||||
|
"version": version,
|
||||||
|
"executables": [
|
||||||
|
{
|
||||||
|
"path": "mpc-qt.exe",
|
||||||
|
"symlink": [],
|
||||||
|
"add_to_devenv_path": False,
|
||||||
|
"checksum": "d7ee46b0d4a61a26f8acd5d5fd4da2d252d6bc80c5cab6a55db06e853f2acefb",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"add_to_devenv_script": [],
|
||||||
|
}
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
version = "0.8.2"
|
||||||
|
result.append({
|
||||||
|
"label": "nvim",
|
||||||
|
"manifests": [
|
||||||
|
{
|
||||||
|
"download_url": f"https://github.com/neovim/neovim/releases/download/v{version}/nvim-win64.zip",
|
||||||
|
"download_checksum": "e2d53c6fd4a3caefbff47765d63d1640a5a134de46623ed8e3f9bf547791c26f",
|
||||||
|
"version": version,
|
||||||
|
"executables": [
|
||||||
|
{
|
||||||
|
"path": "bin/nvim.exe",
|
||||||
|
"symlink": [],
|
||||||
|
"add_to_devenv_path": True,
|
||||||
|
"checksum": "dd8b045e9a76bea6add3e7a727387aef6996846907e061df07971329b9464faf",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"add_to_devenv_script": [],
|
||||||
|
}
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
version = "0.10.3"
|
||||||
|
result.append({
|
||||||
|
"label": "neovide",
|
||||||
|
"manifests": [
|
||||||
|
{
|
||||||
|
"download_url": f"https://github.com/neovide/neovide/releases/download/{version}/neovide-windows.zip",
|
||||||
|
"download_checksum": "ec54f811e5cb271102751694124380f4a58ae5edf99a1a267e8b070a362f8297",
|
||||||
|
"version": version,
|
||||||
|
"executables": [
|
||||||
|
{
|
||||||
|
"path": "neovide.exe",
|
||||||
|
"symlink": ["neovide.exe"],
|
||||||
|
"add_to_devenv_path": False,
|
||||||
|
"checksum": "2c1df8ec7287f927554ebd9ad5cd0da34d7e72c3384fe266080ddf612adf6e5a",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"add_to_devenv_script": [],
|
||||||
|
}
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
version = "1.26.2"
|
||||||
|
result.append({
|
||||||
|
"label": "ImHex",
|
||||||
|
"manifests": [
|
||||||
|
{
|
||||||
|
"download_url": f"https://github.com/WerWolv/ImHex/releases/download/v{version}/imhex-{version}-Windows-Portable.zip",
|
||||||
|
"download_checksum": "4f58097c3ccee88d8dff0d48da0f239af8a9d444903cc19a3369f63caa8d77e6",
|
||||||
|
"version": f"version",
|
||||||
|
"executables": [
|
||||||
|
{
|
||||||
|
"path": "imhex.exe",
|
||||||
|
"symlink": [],
|
||||||
|
"add_to_devenv_path": False,
|
||||||
|
"checksum": "ddd448c0d8fe71295bbcc5b52c9e9f4b06956a79572b7d634436a49728f5f341",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"add_to_devenv_script": [],
|
||||||
|
}
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
version = "22.3"
|
||||||
|
result.append({
|
||||||
|
"label": "MobaXTerm",
|
||||||
|
"manifests": [
|
||||||
|
{
|
||||||
|
"download_url": f"https://download.mobatek.net/2232022120824733/MobaXterm_Portable_v{version}.zip",
|
||||||
|
"download_checksum": "c8de508d6731f31a73f061e58942691466d1d24cfa941e642e16e0930be2fad9",
|
||||||
|
"version": version,
|
||||||
|
"executables": [
|
||||||
|
{
|
||||||
|
"path": f"MobaXTerm_Personal_{version}.exe",
|
||||||
|
"symlink": [],
|
||||||
|
"add_to_devenv_path": False,
|
||||||
|
"checksum": "e47cb54645a368411c5d6b6cbfa7e25980a2a674d7d0c082f5137b6e77a2f362",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"add_to_devenv_script": [],
|
||||||
|
}
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
version = "3.0.5847"
|
||||||
|
result.append({
|
||||||
|
"label": "SystemInformer",
|
||||||
|
"manifests": [
|
||||||
|
{
|
||||||
|
"download_url": f"https://github.com/winsiderss/si-builds/releases/download/{version}/systeminformer-{version}-bin.zip",
|
||||||
|
"download_checksum": "4557e58f698048e882515faac89c9c7f654247dbf4bd656ceed5c3f97afef77d",
|
||||||
|
"version": "3.0.5847",
|
||||||
|
"executables": [
|
||||||
|
{
|
||||||
|
"path": "amd64/SystemInformer.exe",
|
||||||
|
"symlink": [],
|
||||||
|
"add_to_devenv_path": False,
|
||||||
|
"checksum": "8a6e9dfd145e5cb8d03ec3db1b7b0163325be33e5c8fdd4126e9f8df2af2a39c",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"add_to_devenv_script": [],
|
||||||
|
}
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
version = "13.0.0"
|
||||||
|
result.append({
|
||||||
|
"label": "ripgrep",
|
||||||
|
"manifests": [
|
||||||
|
{
|
||||||
|
"download_url": f"https://github.com/BurntSushi/ripgrep/releases/download/{version}/ripgrep-{version}-x86_64-pc-windows-msvc.zip",
|
||||||
|
"download_checksum": "a47ace6f654c5ffa236792fc3ee3fefd9c7e88e026928b44da801acb72124aa8",
|
||||||
|
"version": version,
|
||||||
|
"executables": [
|
||||||
|
{
|
||||||
|
"path": "rg.exe",
|
||||||
|
"symlink": ["rg.exe"],
|
||||||
|
"add_to_devenv_path": False,
|
||||||
|
"checksum": "ab5595a4f7a6b918cece0e7e22ebc883ead6163948571419a1dd5cd3c7f37972",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"add_to_devenv_script": [],
|
||||||
|
}
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
version = "2.0.0"
|
||||||
|
result.append({
|
||||||
|
"label": "sioyek",
|
||||||
|
"manifests": [
|
||||||
|
{
|
||||||
|
"download_url": f"https://github.com/ahrm/sioyek/releases/download/v{version}/sioyek-release-windows-portable.zip",
|
||||||
|
"download_checksum": "1f4fedbb38c0dc46bbba4bb95d0d6fab39fcf3525092ac26d92c891684d2bf8d",
|
||||||
|
"version": version,
|
||||||
|
"executables": [
|
||||||
|
{
|
||||||
|
"path": "sioyek.exe",
|
||||||
|
"symlink": [],
|
||||||
|
"add_to_devenv_path": False,
|
||||||
|
"checksum": "6c660f0f7265fabe6d943d15d9b5c7e85f2dbcf7fecb7d2cd0639e7086b1c034",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"add_to_devenv_script": [],
|
||||||
|
}
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
version = "8.6.0"
|
||||||
|
result.append({
|
||||||
|
"label": "fd",
|
||||||
|
"manifests": [
|
||||||
|
{
|
||||||
|
"download_url": f"https://github.com/sharkdp/fd/releases/download/v{version}/fd-v{version}-x86_64-pc-windows-msvc.zip",
|
||||||
|
"download_checksum": "9cff97eb1c024ed94cc76a4b2d924ab3df04b37e7430c282b8188a13f1653ebe",
|
||||||
|
"version": version,
|
||||||
|
"executables": [
|
||||||
|
{
|
||||||
|
"path": "fd.exe",
|
||||||
|
"symlink": ["fd.exe"],
|
||||||
|
"add_to_devenv_path": False,
|
||||||
|
"checksum": "a93ab08528896556ba3a6c262c8d73b275df2ce7a4138f5323f3eff414403f33",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"add_to_devenv_script": [
|
||||||
|
"set FZF_DEFAULT_OPTS=--multi --layout=reverse",
|
||||||
|
"set FZF_DEFAULT_COMMAND=fd --type f --strip-cwd-prefix --hidden --follow --exclude .git --exclude .cache --exclude .vs",
|
||||||
|
],
|
||||||
|
}
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
version = "4_12"
|
||||||
|
result.append({
|
||||||
|
"label": "WizTree",
|
||||||
|
"manifests": [
|
||||||
|
{
|
||||||
|
"download_url": f"https://www.diskanalyzer.com/files/wiztree_{version}_portable.zip",
|
||||||
|
"download_checksum": "f6b71fc54a9bb3f277efdf8afcd45df8ddc1759533f3236437309dae7778b168",
|
||||||
|
"version": version,
|
||||||
|
"executables": [
|
||||||
|
{
|
||||||
|
"path": "wiztree64.exe",
|
||||||
|
"symlink": [],
|
||||||
|
"add_to_devenv_path": False,
|
||||||
|
"checksum": "e2157dc64629a29e1713a845e5a9e7cab89d79a7390820c1bfda05c7de989c3d",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"add_to_devenv_script": [],
|
||||||
|
}
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
return result
|
371
win_portable_msvc.py
Normal file
371
win_portable_msvc.py
Normal file
@ -0,0 +1,371 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# This script has been gratefully sourced from Martins Mozeiko of HMN
|
||||||
|
# https://gist.github.com/mmozeiko/7f3162ec2988e81e56d5c4e22cde9977
|
||||||
|
#
|
||||||
|
# Further modifications by https://github.com/doy-lee with the primary purpose
|
||||||
|
# of facilitating multiple versions to be stored in the same root directory
|
||||||
|
# ('Redist' in the SDK was unversioned, store it versioned like all other
|
||||||
|
# folders, skip the downloading of MSVC or the SDK if we only need one of them).
|
||||||
|
#
|
||||||
|
# Changelog
|
||||||
|
# 2023-01-28
|
||||||
|
# - Inital revision from mmozeiko
|
||||||
|
# https://gist.github.com/mmozeiko/7f3162ec2988e81e56d5c4e22cde9977/6863f19cb98b933c7535acf3d59ac64268c6bd1b
|
||||||
|
# - Add individual scripts to source variables for MSVC and Windows 10
|
||||||
|
# separately "msvc-{version}.bat" and "win-sdk-{version}.bat"
|
||||||
|
# - Add '--no-sdk' and '--no-msvc' to prevent the download and installation of
|
||||||
|
# the Windows SDK and MSVC respectively.
|
||||||
|
# - Installation used to create 'Windows Kit/10/Redist' and unpack a D3D and MBN
|
||||||
|
# folder without being versioned. These folders are now placed under
|
||||||
|
# a versioned sub-directory to preserve the binaries and allow subsequent
|
||||||
|
# side-by-side installation of other versions of the SDK.
|
||||||
|
|
||||||
|
import io
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import json
|
||||||
|
import shutil
|
||||||
|
import hashlib
|
||||||
|
import zipfile
|
||||||
|
import tempfile
|
||||||
|
import argparse
|
||||||
|
import subprocess
|
||||||
|
import urllib.request
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
OUTPUT = Path("msvc") # output folder
|
||||||
|
|
||||||
|
# other architectures may work or may not - not really tested
|
||||||
|
HOST = "x64" # or x86
|
||||||
|
TARGET = "x64" # or x86, arm, arm64
|
||||||
|
|
||||||
|
MANIFEST_URL = "https://aka.ms/vs/17/release/channel"
|
||||||
|
|
||||||
|
|
||||||
|
def download(url):
|
||||||
|
with urllib.request.urlopen(url) as res:
|
||||||
|
return res.read()
|
||||||
|
|
||||||
|
def download_progress(url, check, name, f):
|
||||||
|
data = io.BytesIO()
|
||||||
|
with urllib.request.urlopen(url) as res:
|
||||||
|
total = int(res.headers["Content-Length"])
|
||||||
|
size = 0
|
||||||
|
while True:
|
||||||
|
block = res.read(1<<20)
|
||||||
|
if not block:
|
||||||
|
break
|
||||||
|
f.write(block)
|
||||||
|
data.write(block)
|
||||||
|
size += len(block)
|
||||||
|
perc = size * 100 // total
|
||||||
|
print(f"\r{name} ... {perc}%", end="")
|
||||||
|
print()
|
||||||
|
data = data.getvalue()
|
||||||
|
digest = hashlib.sha256(data).hexdigest()
|
||||||
|
if check.lower() != digest:
|
||||||
|
exit(f"Hash mismatch for f{pkg}")
|
||||||
|
return data
|
||||||
|
|
||||||
|
# super crappy msi format parser just to find required .cab files
|
||||||
|
def get_msi_cabs(msi):
|
||||||
|
index = 0
|
||||||
|
while True:
|
||||||
|
index = msi.find(b".cab", index+4)
|
||||||
|
if index < 0:
|
||||||
|
return
|
||||||
|
yield msi[index-32:index+4].decode("ascii")
|
||||||
|
|
||||||
|
def first(items, cond):
|
||||||
|
return next(item for item in items if cond(item))
|
||||||
|
|
||||||
|
|
||||||
|
### parse command-line arguments
|
||||||
|
|
||||||
|
ap = argparse.ArgumentParser()
|
||||||
|
ap.add_argument("--show-versions", const=True, action="store_const", help="Show available MSVC and Windows SDK versions")
|
||||||
|
ap.add_argument("--accept-license", const=True, action="store_const", help="Automatically accept license")
|
||||||
|
ap.add_argument("--msvc-version", help="Get specific MSVC version")
|
||||||
|
ap.add_argument("--sdk-version", help="Get specific Windows SDK version")
|
||||||
|
ap.add_argument("--no-msvc", const=True, action="store_const", help="Skip download and installing of msvc")
|
||||||
|
ap.add_argument("--no-sdk", const=True, action="store_const", help="Skip download and installing of Windows SDK")
|
||||||
|
args = ap.parse_args()
|
||||||
|
|
||||||
|
### get main manifest
|
||||||
|
|
||||||
|
manifest = json.loads(download(MANIFEST_URL))
|
||||||
|
|
||||||
|
|
||||||
|
### download VS manifest
|
||||||
|
|
||||||
|
vs = first(manifest["channelItems"], lambda x: x["id"] == "Microsoft.VisualStudio.Manifests.VisualStudio")
|
||||||
|
payload = vs["payloads"][0]["url"]
|
||||||
|
|
||||||
|
vsmanifest = json.loads(download(payload))
|
||||||
|
|
||||||
|
|
||||||
|
### find MSVC & WinSDK versions
|
||||||
|
|
||||||
|
packages = {}
|
||||||
|
for p in vsmanifest["packages"]:
|
||||||
|
packages.setdefault(p["id"].lower(), []).append(p)
|
||||||
|
|
||||||
|
msvc = {}
|
||||||
|
sdk = {}
|
||||||
|
|
||||||
|
for pid,p in packages.items():
|
||||||
|
if pid.startswith("Microsoft.VisualStudio.Component.VC.".lower()) and pid.endswith(".x86.x64".lower()):
|
||||||
|
pver = ".".join(pid.split(".")[4:6])
|
||||||
|
if pver[0].isnumeric():
|
||||||
|
msvc[pver] = pid
|
||||||
|
elif pid.startswith("Microsoft.VisualStudio.Component.Windows10SDK.".lower()) or \
|
||||||
|
pid.startswith("Microsoft.VisualStudio.Component.Windows11SDK.".lower()):
|
||||||
|
pver = pid.split(".")[-1]
|
||||||
|
if pver.isnumeric():
|
||||||
|
sdk[pver] = pid
|
||||||
|
|
||||||
|
if args.show_versions:
|
||||||
|
print("MSVC versions:", " ".join(sorted(msvc.keys())))
|
||||||
|
print("Windows SDK versions:", " ".join(sorted(sdk.keys())))
|
||||||
|
exit(0)
|
||||||
|
|
||||||
|
install_sdk = not args.no_sdk
|
||||||
|
install_msvc = not args.no_msvc
|
||||||
|
if args.no_sdk and args.no_msvc:
|
||||||
|
exit()
|
||||||
|
|
||||||
|
msvc_ver = args.msvc_version or max(sorted(msvc.keys()))
|
||||||
|
sdk_ver = args.sdk_version or max(sorted(sdk.keys()))
|
||||||
|
|
||||||
|
info_line = "Downloading"
|
||||||
|
if install_msvc:
|
||||||
|
if msvc_ver in msvc:
|
||||||
|
msvc_pid = msvc[msvc_ver]
|
||||||
|
msvc_ver = ".".join(msvc_pid.split(".")[4:-2])
|
||||||
|
else:
|
||||||
|
exit(f"Unknown MSVC version: f{args.msvc_version}")
|
||||||
|
info_line += f" MSVC v{msvc_ver}"
|
||||||
|
|
||||||
|
if install_sdk:
|
||||||
|
if sdk_ver in sdk:
|
||||||
|
sdk_pid = sdk[sdk_ver]
|
||||||
|
else:
|
||||||
|
exit(f"Unknown Windows SDK version: f{args.sdk_version}")
|
||||||
|
info_line += f" Windows SDK v{sdk_ver}"
|
||||||
|
|
||||||
|
print(info_line)
|
||||||
|
|
||||||
|
|
||||||
|
### agree to license
|
||||||
|
|
||||||
|
tools = first(manifest["channelItems"], lambda x: x["id"] == "Microsoft.VisualStudio.Product.BuildTools")
|
||||||
|
resource = first(tools["localizedResources"], lambda x: x["language"] == "en-us")
|
||||||
|
license = resource["license"]
|
||||||
|
|
||||||
|
if not args.accept_license:
|
||||||
|
accept = input(f"Do you accept Visual Studio license at {license} [Y/N] ? ")
|
||||||
|
if not accept or accept[0].lower() != "y":
|
||||||
|
exit(0)
|
||||||
|
|
||||||
|
OUTPUT.mkdir(exist_ok=True)
|
||||||
|
total_download = 0
|
||||||
|
|
||||||
|
### download MSVC
|
||||||
|
|
||||||
|
if install_msvc:
|
||||||
|
msvc_packages = [
|
||||||
|
# MSVC binaries
|
||||||
|
f"microsoft.vc.{msvc_ver}.tools.host{HOST}.target{TARGET}.base",
|
||||||
|
f"microsoft.vc.{msvc_ver}.tools.host{HOST}.target{TARGET}.res.base",
|
||||||
|
# MSVC headers
|
||||||
|
f"microsoft.vc.{msvc_ver}.crt.headers.base",
|
||||||
|
# MSVC libs
|
||||||
|
f"microsoft.vc.{msvc_ver}.crt.{TARGET}.desktop.base",
|
||||||
|
f"microsoft.vc.{msvc_ver}.crt.{TARGET}.store.base",
|
||||||
|
# MSVC runtime source
|
||||||
|
f"microsoft.vc.{msvc_ver}.crt.source.base",
|
||||||
|
# ASAN
|
||||||
|
f"microsoft.vc.{msvc_ver}.asan.headers.base",
|
||||||
|
f"microsoft.vc.{msvc_ver}.asan.{TARGET}.base",
|
||||||
|
# MSVC redist
|
||||||
|
#f"microsoft.vc.{msvc_ver}.crt.redist.x64.base",
|
||||||
|
]
|
||||||
|
|
||||||
|
for pkg in msvc_packages:
|
||||||
|
p = first(packages[pkg], lambda p: p.get("language") in (None, "en-US"))
|
||||||
|
for payload in p["payloads"]:
|
||||||
|
with tempfile.TemporaryFile() as f:
|
||||||
|
data = download_progress(payload["url"], payload["sha256"], pkg, f)
|
||||||
|
total_download += len(data)
|
||||||
|
with zipfile.ZipFile(f) as z:
|
||||||
|
for name in z.namelist():
|
||||||
|
if name.startswith("Contents/"):
|
||||||
|
out = OUTPUT / Path(name).relative_to("Contents")
|
||||||
|
out.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
out.write_bytes(z.read(name))
|
||||||
|
|
||||||
|
|
||||||
|
### download Windows SDK
|
||||||
|
|
||||||
|
if install_sdk:
|
||||||
|
sdk_packages = [
|
||||||
|
# Windows SDK tools (like rc.exe & mt.exe)
|
||||||
|
f"Windows SDK for Windows Store Apps Tools-x86_en-us.msi",
|
||||||
|
# Windows SDK headers
|
||||||
|
f"Windows SDK for Windows Store Apps Headers-x86_en-us.msi",
|
||||||
|
f"Windows SDK Desktop Headers x86-x86_en-us.msi",
|
||||||
|
# Windows SDK libs
|
||||||
|
f"Windows SDK for Windows Store Apps Libs-x86_en-us.msi",
|
||||||
|
f"Windows SDK Desktop Libs {TARGET}-x86_en-us.msi",
|
||||||
|
# CRT headers & libs
|
||||||
|
f"Universal CRT Headers Libraries and Sources-x86_en-us.msi",
|
||||||
|
# CRT redist
|
||||||
|
#"Universal CRT Redistributable-x86_en-us.msi",
|
||||||
|
]
|
||||||
|
|
||||||
|
with tempfile.TemporaryDirectory() as d:
|
||||||
|
dst = Path(d)
|
||||||
|
|
||||||
|
sdk_pkg = packages[sdk_pid][0]
|
||||||
|
sdk_pkg = packages[first(sdk_pkg["dependencies"], lambda x: True).lower()][0]
|
||||||
|
|
||||||
|
msi = []
|
||||||
|
cabs = []
|
||||||
|
|
||||||
|
# download msi files
|
||||||
|
for pkg in sdk_packages:
|
||||||
|
payload = first(sdk_pkg["payloads"], lambda p: p["fileName"] == f"Installers\\{pkg}")
|
||||||
|
msi.append(dst / pkg)
|
||||||
|
with open(dst / pkg, "wb") as f:
|
||||||
|
data = download_progress(payload["url"], payload["sha256"], pkg, f)
|
||||||
|
total_download += len(data)
|
||||||
|
cabs += list(get_msi_cabs(data))
|
||||||
|
|
||||||
|
# download .cab files
|
||||||
|
for pkg in cabs:
|
||||||
|
payload = first(sdk_pkg["payloads"], lambda p: p["fileName"] == f"Installers\\{pkg}")
|
||||||
|
with open(dst / pkg, "wb") as f:
|
||||||
|
download_progress(payload["url"], payload["sha256"], pkg, f)
|
||||||
|
|
||||||
|
print("Unpacking msi files...")
|
||||||
|
|
||||||
|
# run msi installers
|
||||||
|
for m in msi:
|
||||||
|
subprocess.check_call(["msiexec.exe", "/a", m, "/quiet", "/qn", f"TARGETDIR={OUTPUT.resolve()}"])
|
||||||
|
|
||||||
|
|
||||||
|
### versions
|
||||||
|
|
||||||
|
msvcv = ""
|
||||||
|
sdkv = ""
|
||||||
|
|
||||||
|
if install_msvc:
|
||||||
|
msvcv = list((OUTPUT / "VC/Tools/MSVC").glob("*"))[0].name
|
||||||
|
|
||||||
|
if install_sdk:
|
||||||
|
sdkv = list((OUTPUT / "Windows Kits/10/bin").glob("*"))[0].name
|
||||||
|
|
||||||
|
# place debug CRT runtime into MSVC folder (not what real Visual Studio installer does... but is reasonable)
|
||||||
|
|
||||||
|
if install_msvc:
|
||||||
|
dst = str(OUTPUT / "VC/Tools/MSVC" / msvcv / f"bin/Host{HOST}/{TARGET}")
|
||||||
|
|
||||||
|
pkg = "microsoft.visualcpp.runtimedebug.14"
|
||||||
|
dbg = packages[pkg][0]
|
||||||
|
payload = first(dbg["payloads"], lambda p: p["fileName"] == "cab1.cab")
|
||||||
|
try:
|
||||||
|
with tempfile.TemporaryFile(suffix=".cab", delete=False) as f:
|
||||||
|
data = download_progress(payload["url"], payload["sha256"], pkg, f)
|
||||||
|
total_download += len(data)
|
||||||
|
subprocess.check_call(["expand.exe", f.name, "-F:*", dst], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||||
|
finally:
|
||||||
|
os.unlink(f.name)
|
||||||
|
|
||||||
|
# place the folders under the Redist folder in the SDK under a versioned folder to allow other versions to be installed
|
||||||
|
|
||||||
|
if install_sdk:
|
||||||
|
redist_dir = OUTPUT / "Windows Kits/10/Redist"
|
||||||
|
redist_versioned_dir = redist_dir / f'{sdkv}'
|
||||||
|
|
||||||
|
if not os.path.exists(redist_versioned_dir):
|
||||||
|
os.makedirs(redist_versioned_dir)
|
||||||
|
|
||||||
|
for file_name in os.listdir(redist_dir):
|
||||||
|
if not file_name.startswith('10.0.'): # Simple heuristic
|
||||||
|
shutil.move((redist_dir / file_name), redist_versioned_dir)
|
||||||
|
|
||||||
|
### cleanup
|
||||||
|
|
||||||
|
shutil.rmtree(OUTPUT / "Common7", ignore_errors=True)
|
||||||
|
if install_msvc:
|
||||||
|
for f in ["Auxiliary", f"lib/{TARGET}/store", f"lib/{TARGET}/uwp"]:
|
||||||
|
shutil.rmtree(OUTPUT / "VC/Tools/MSVC" / msvcv / f)
|
||||||
|
for f in OUTPUT.glob("*.msi"):
|
||||||
|
f.unlink()
|
||||||
|
if install_sdk:
|
||||||
|
for f in ["Catalogs", "DesignTime", f"bin/{sdkv}/chpe", f"Lib/{sdkv}/ucrt_enclave"]:
|
||||||
|
shutil.rmtree(OUTPUT / "Windows Kits/10" / f, ignore_errors=True)
|
||||||
|
for arch in ["x86", "x64", "arm", "arm64"]:
|
||||||
|
if arch != TARGET:
|
||||||
|
if install_msvc:
|
||||||
|
shutil.rmtree(OUTPUT / "VC/Tools/MSVC" / msvcv / f"bin/Host{arch}", ignore_errors=True)
|
||||||
|
if install_sdk:
|
||||||
|
shutil.rmtree(OUTPUT / "Windows Kits/10/bin" / sdkv / arch)
|
||||||
|
shutil.rmtree(OUTPUT / "Windows Kits/10/Lib" / sdkv / "ucrt" / arch)
|
||||||
|
shutil.rmtree(OUTPUT / "Windows Kits/10/Lib" / sdkv / "um" / arch)
|
||||||
|
|
||||||
|
|
||||||
|
### setup.bat
|
||||||
|
|
||||||
|
if install_msvc and install_sdk:
|
||||||
|
SETUP = f"""@echo off
|
||||||
|
|
||||||
|
set MSVC_VERSION={msvcv}
|
||||||
|
set MSVC_HOST=Host{HOST}
|
||||||
|
set MSVC_ARCH={TARGET}
|
||||||
|
set SDK_VERSION={sdkv}
|
||||||
|
set SDK_ARCH={TARGET}
|
||||||
|
|
||||||
|
set MSVC_ROOT=%~dp0VC\\Tools\\MSVC\\%MSVC_VERSION%
|
||||||
|
set SDK_INCLUDE=%~dp0Windows Kits\\10\\Include\\%SDK_VERSION%
|
||||||
|
set SDK_LIBS=%~dp0Windows Kits\\10\\Lib\\%SDK_VERSION%
|
||||||
|
|
||||||
|
set VCToolsInstallDir=%MSVC_ROOT%\\
|
||||||
|
set PATH=%MSVC_ROOT%\\bin\\%MSVC_HOST%\\%MSVC_ARCH%;%~dp0Windows Kits\\10\\bin\\%SDK_VERSION%\\%SDK_ARCH%;%~dp0Windows Kits\\10\\bin\\%SDK_VERSION%\\%SDK_ARCH%\\ucrt;%PATH%
|
||||||
|
set INCLUDE=%MSVC_ROOT%\\include;%SDK_INCLUDE%\\ucrt;%SDK_INCLUDE%\\shared;%SDK_INCLUDE%\\um;%SDK_INCLUDE%\\winrt;%SDK_INCLUDE%\\cppwinrt
|
||||||
|
set LIB=%MSVC_ROOT%\\lib\\%MSVC_ARCH%;%SDK_LIBS%\\ucrt\\%SDK_ARCH%;%SDK_LIBS%\\um\\%SDK_ARCH%
|
||||||
|
"""
|
||||||
|
(OUTPUT / "setup.bat").write_text(SETUP)
|
||||||
|
|
||||||
|
if install_msvc:
|
||||||
|
MSVC_SCRIPT = f"""@echo off
|
||||||
|
|
||||||
|
set MSVC_VERSION={msvcv}
|
||||||
|
set MSVC_HOST=Host{HOST}
|
||||||
|
set MSVC_ARCH={TARGET}
|
||||||
|
set MSVC_ROOT=%~dp0VC\\Tools\\MSVC\\%MSVC_VERSION%
|
||||||
|
|
||||||
|
set VCToolsInstallDir=%MSVC_ROOT%\\;%VCToolsInstallDir%
|
||||||
|
set PATH=%MSVC_ROOT%\\bin\\%MSVC_HOST%\\%MSVC_ARCH%;%PATH%
|
||||||
|
set INCLUDE=%MSVC_ROOT%\\include;%INCLUDE%
|
||||||
|
set LIB=%MSVC_ROOT%\\lib\\%MSVC_ARCH%;%LIB%
|
||||||
|
"""
|
||||||
|
(OUTPUT / f"msvc-{msvcv}.bat").write_text(MSVC_SCRIPT)
|
||||||
|
|
||||||
|
if install_sdk:
|
||||||
|
WIN10_SDK_SCRIPT = f"""@echo off
|
||||||
|
|
||||||
|
set SDK_VERSION={sdkv}
|
||||||
|
set SDK_ARCH={TARGET}
|
||||||
|
set SDK_INCLUDE=%~dp0Windows Kits\\10\\Include\\%SDK_VERSION%
|
||||||
|
set SDK_LIBS=%~dp0Windows Kits\\10\\Lib\\%SDK_VERSION%
|
||||||
|
|
||||||
|
set PATH=%~dp0Windows Kits\\10\\bin\\%SDK_VERSION%\\%SDK_ARCH%;%~dp0Windows Kits\\10\\bin\\%SDK_VERSION%\\%SDK_ARCH%\\ucrt;%PATH%
|
||||||
|
set INCLUDE=%SDK_INCLUDE%\\ucrt;%SDK_INCLUDE%\\shared;%SDK_INCLUDE%\\um;%SDK_INCLUDE%\\winrt;%SDK_INCLUDE%\\cppwinrt
|
||||||
|
set LIB=%SDK_LIBS%\\ucrt\\%SDK_ARCH%;%SDK_LIBS%\\um\\%SDK_ARCH%
|
||||||
|
"""
|
||||||
|
(OUTPUT / f"win-sdk-{sdkv}.bat").write_text(WIN10_SDK_SCRIPT)
|
||||||
|
|
||||||
|
print(f"Total downloaded: {total_download>>20} MB")
|
||||||
|
print("Done!")
|
279
win_setup.py
Normal file
279
win_setup.py
Normal file
@ -0,0 +1,279 @@
|
|||||||
|
import devenver
|
||||||
|
import pprint
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import pathlib
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import tempfile
|
||||||
|
import devenver_manifest
|
||||||
|
import urllib.request
|
||||||
|
|
||||||
|
def git_clone(install_dir, git_exe, url, commit_hash):
|
||||||
|
devenver.lprint(f"Git clone {url} to {install_dir}", level=0)
|
||||||
|
# Clone repository if it does not exist
|
||||||
|
if not os.path.exists(install_dir):
|
||||||
|
devenver.lprint(f"Cloning to {install_dir}")
|
||||||
|
subprocess.run(f"{git_exe} clone {url} {install_dir}")
|
||||||
|
|
||||||
|
# Determine current git hash
|
||||||
|
result = subprocess.run(f"{git_exe} rev-parse --short HEAD",
|
||||||
|
cwd=install_dir,
|
||||||
|
capture_output=True)
|
||||||
|
curr_commit_hash = result.stdout.decode("utf-8").strip()
|
||||||
|
|
||||||
|
# Checkout correct target of Odin
|
||||||
|
if curr_commit_hash != commit_hash:
|
||||||
|
subprocess.run(f"{git_exe} checkout master", cwd=install_dir)
|
||||||
|
subprocess.run(f"{git_exe} pull origin master", cwd=install_dir)
|
||||||
|
subprocess.run(f"{git_exe} checkout {commit_hash}", cwd=install_dir)
|
||||||
|
|
||||||
|
# Run DEVenver, installing the portable apps
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
user_app_list = devenver_manifest.get_manifest()
|
||||||
|
installed_apps = devenver.run(user_app_list)
|
||||||
|
|
||||||
|
# Install MSVC
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
devenver.print_header("Install MSVC & Windows 10 SDK")
|
||||||
|
msvc_script = pathlib.Path(devenver.script_dir, "win_portable_msvc.py")
|
||||||
|
msvc_version = "14.34"
|
||||||
|
win10_sdk_version = "22621"
|
||||||
|
|
||||||
|
msvc_install_dir = devenver.base_install_dir / "msvc"
|
||||||
|
|
||||||
|
# Basic heuristic to see if we"ve already installed the MSVC/SDK version
|
||||||
|
msvc_installed = False
|
||||||
|
win10_sdk_installed = False
|
||||||
|
|
||||||
|
msvc_find_test_dir = msvc_install_dir / "VC/Tools/MSVC"
|
||||||
|
win10_sdk_find_test_dir = msvc_install_dir / "Windows Kits/10"
|
||||||
|
|
||||||
|
if os.path.exists(msvc_find_test_dir):
|
||||||
|
for file_name in os.listdir(msvc_find_test_dir):
|
||||||
|
msvc_installed = file_name.startswith(msvc_version)
|
||||||
|
if msvc_installed == True:
|
||||||
|
devenver.lprint(f"MSVC {msvc_version} install detected (skip download) in {msvc_find_test_dir}\\{file_name}")
|
||||||
|
break
|
||||||
|
if not msvc_installed:
|
||||||
|
devenver.lprint(f"MSVC {msvc_version} install not detected (need to download) in {msvc_find_test_dir}")
|
||||||
|
|
||||||
|
if os.path.exists(win10_sdk_find_test_dir):
|
||||||
|
for file_name in os.listdir(win10_sdk_find_test_dir / "bin"):
|
||||||
|
# Check if directory contains version substring, 22621, e.g. "10.0.22621.0"
|
||||||
|
win10_sdk_installed = file_name.count(win10_sdk_version) > 0
|
||||||
|
if win10_sdk_installed == True:
|
||||||
|
install_locations = f"{win10_sdk_find_test_dir}\\*\\{file_name}"
|
||||||
|
devenver.lprint(f"Windows 10 SDK {win10_sdk_version} install detected (skip download) in {install_locations}")
|
||||||
|
break
|
||||||
|
if not win10_sdk_installed:
|
||||||
|
devenver.lprint(f"Windows 10 SDK {win10_sdk_version} not detected (need to download) in {win10_sdk_find_test_dir}")
|
||||||
|
|
||||||
|
# Install MSVC
|
||||||
|
if msvc_installed == False or win10_sdk_installed == False:
|
||||||
|
with tempfile.TemporaryDirectory() as temp_dir:
|
||||||
|
|
||||||
|
# Invoke the MSVC script to download MSVC to disk
|
||||||
|
command = f"'{sys.executable}' '{msvc_script}' --accept-license"
|
||||||
|
line = "Invoking MSVC script to install"
|
||||||
|
if msvc_installed:
|
||||||
|
command += " --no-msvc"
|
||||||
|
else:
|
||||||
|
command += f" --msvc-version {msvc_version}"
|
||||||
|
line += f" MSVC {msvc_version}"
|
||||||
|
|
||||||
|
if win10_sdk_installed:
|
||||||
|
command += " --no-sdk"
|
||||||
|
else:
|
||||||
|
command += f" --sdk-version {win10_sdk_version}"
|
||||||
|
line += f" Windows 10 SDK {win10_sdk_version}"
|
||||||
|
|
||||||
|
devenver.lprint(line)
|
||||||
|
devenver.lprint(f"Command: {command}")
|
||||||
|
subprocess.run(command, cwd=temp_dir)
|
||||||
|
|
||||||
|
# Merge the download MSVC installation to our unified install dir
|
||||||
|
temp_msvc_dir = pathlib.Path(temp_dir, "msvc")
|
||||||
|
for src_dir, dirs, files in os.walk(temp_msvc_dir):
|
||||||
|
install_dir = src_dir.replace(str(temp_msvc_dir), str(msvc_install_dir), 1)
|
||||||
|
if not os.path.exists(install_dir):
|
||||||
|
os.makedirs(install_dir)
|
||||||
|
for file_ in files:
|
||||||
|
src = os.path.join(src_dir, file_)
|
||||||
|
dest = os.path.join(install_dir, file_)
|
||||||
|
if os.path.exists(dest):
|
||||||
|
if os.path.samefile(src, dest):
|
||||||
|
continue
|
||||||
|
os.remove(dest)
|
||||||
|
shutil.move(src, install_dir)
|
||||||
|
|
||||||
|
devenver.lprint(f"MSVC {msvc_version} Windows 10 SDK {win10_sdk_version} installed: {msvc_install_dir}")
|
||||||
|
|
||||||
|
# Install apps dependent on Git
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
devenver.print_header("Install apps that rely on Git")
|
||||||
|
git_exe = installed_apps["Git"][0]['exe_path']
|
||||||
|
|
||||||
|
# Clink Completions
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
clink_git_hash = "fa18736"
|
||||||
|
clink_install_dir = pathlib.Path(devenver.base_install_dir, "clink-completions")
|
||||||
|
git_clone(install_dir=clink_install_dir,
|
||||||
|
git_exe=git_exe,
|
||||||
|
url="https://github.com/vladimir-kotikov/clink-completions",
|
||||||
|
commit_hash=clink_git_hash)
|
||||||
|
|
||||||
|
# Odin
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
odin_git_hash = "9ae1bfb6"
|
||||||
|
odin_install_dir = pathlib.Path(devenver.base_install_dir, "Odin")
|
||||||
|
git_clone(install_dir=odin_install_dir,
|
||||||
|
git_exe=git_exe,
|
||||||
|
url="https://github.com/odin-lang/odin.git",
|
||||||
|
commit_hash=odin_git_hash)
|
||||||
|
|
||||||
|
# TODO: We can't do this yet because the odin build requires a registry hack so
|
||||||
|
# that it knows where to find MSVC.
|
||||||
|
|
||||||
|
# Build Odin
|
||||||
|
# subprocess.run(f"{git_exe} checkout {odin_git_hash}",
|
||||||
|
# cwd=odin_install_dir)
|
||||||
|
|
||||||
|
# Install left-overs
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
devenver.print_header("Install configuration files")
|
||||||
|
|
||||||
|
# Copy init.vim to NVIM directory
|
||||||
|
internal_dir = pathlib.Path(os.path.dirname(os.path.abspath(__file__)), "Internal")
|
||||||
|
nvim_init_dir = pathlib.Path(os.path.expanduser("~"), "AppData", "Local", "nvim")
|
||||||
|
nvim_config_dest_path = nvim_init_dir / "init.vim"
|
||||||
|
nvim_config_src_path = internal_dir / "os_nvim_init.vim"
|
||||||
|
|
||||||
|
devenver.lprint(f"Installing NVIM config to {nvim_config_dest_path}")
|
||||||
|
nvim_init_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
shutil.copy(nvim_config_src_path, nvim_config_dest_path)
|
||||||
|
|
||||||
|
# Download vim.plug to NVIM init directory
|
||||||
|
nvim_plug_vim_dir = nvim_init_dir / "autoload"
|
||||||
|
nvim_plug_vim_path = nvim_plug_vim_dir / "plug.vim"
|
||||||
|
nvim_plug_vim_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
if not os.path.exists(nvim_plug_vim_path):
|
||||||
|
devenver.lprint(f"Installing NVIM plugin manager to {nvim_plug_vim_path}")
|
||||||
|
urllib.request.urlretrieve("https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim",
|
||||||
|
nvim_plug_vim_path)
|
||||||
|
|
||||||
|
# Install wezterm configuration
|
||||||
|
wezterm_install_dir = installed_apps["WezTerm"][0]["install_dir"]
|
||||||
|
wezterm_exe_path = installed_apps["WezTerm"][0]["exe_path"]
|
||||||
|
wezterm_config_dest_path = wezterm_install_dir / "wezterm.lua"
|
||||||
|
|
||||||
|
devenver.lprint(f"Installing WezTerm config to {wezterm_config_dest_path}")
|
||||||
|
|
||||||
|
clink_install_dir = installed_apps["clink"][0]["install_dir"]
|
||||||
|
clink_exe_path = clink_install_dir.relative_to(devenver.base_install_dir) / "clink_x64.exe"
|
||||||
|
clink_exe_path_for_wezterm = str(clink_exe_path).replace("\\", "\\\\")
|
||||||
|
|
||||||
|
wezterm_lua_buffer = f"""local wezterm = require 'wezterm';
|
||||||
|
|
||||||
|
local default_prog
|
||||||
|
local set_environment_variables = {{}}
|
||||||
|
|
||||||
|
if wezterm.target_triple == "x86_64-pc-windows-msvc" then
|
||||||
|
|
||||||
|
clink_exe = string.format("%s\\\\..\\\\..\\\\{clink_exe_path_for_wezterm}", wezterm.executable_dir)
|
||||||
|
devenv_bat = string.format("%s\\\\..\\\\..\\\\devenv.bat", wezterm.executable_dir)
|
||||||
|
msvc_bat = string.format("%s\\\\..\\\\..\\\\msvc\\\\setup.bat", wezterm.executable_dir)
|
||||||
|
|
||||||
|
-- Taken from: https://wezfurlong.org/wezterm/shell-integration.html
|
||||||
|
-- Use OSC 7 as per the above example
|
||||||
|
set_environment_variables['prompt'] =
|
||||||
|
'$E]7;file://localhost/$P$E\\\\$E[32m$T$E[0m $E[35m$P$E[36m$_$G$E[0m '
|
||||||
|
|
||||||
|
-- use a more ls-like output format for dir
|
||||||
|
set_environment_variables['DIRCMD'] = '/d'
|
||||||
|
|
||||||
|
default_prog = {{"cmd.exe", "/s", "/k",
|
||||||
|
clink_exe, "inject", "-q",
|
||||||
|
"&&", "call", devenv_bat,
|
||||||
|
"&&", "call", msvc_bat}}
|
||||||
|
end
|
||||||
|
|
||||||
|
return {{
|
||||||
|
font_size = 10.0,
|
||||||
|
color_scheme = "Peppermint",
|
||||||
|
default_prog = default_prog,
|
||||||
|
set_environment_variables = set_environment_variables,
|
||||||
|
}}
|
||||||
|
"""
|
||||||
|
|
||||||
|
with open(wezterm_config_dest_path, "w") as file:
|
||||||
|
file.write(wezterm_lua_buffer)
|
||||||
|
|
||||||
|
# Wezterm super terminal
|
||||||
|
wezterm_exe_rel_path = pathlib.Path(wezterm_exe_path).relative_to(devenver.base_install_dir)
|
||||||
|
wezterm_terminal_script_path = pathlib.Path(devenver.base_install_dir, "win_terminal.bat")
|
||||||
|
wezterm_terminal_script = f"""@echo off
|
||||||
|
setlocal EnableDelayedExpansion
|
||||||
|
|
||||||
|
set working_dir=
|
||||||
|
if "%~1" neq "" (
|
||||||
|
set working_dir=start --cwd "%~1"
|
||||||
|
set working_dir=!working_dir:\=/!
|
||||||
|
)
|
||||||
|
|
||||||
|
if exist "%~dp0win_terminal_user_config.bat" call "%~dp0win_terminal_user_config.bat"
|
||||||
|
start "" /MAX "%~dp0{wezterm_exe_rel_path}" !working_dir!
|
||||||
|
"""
|
||||||
|
|
||||||
|
devenver.lprint(f"Installing WezTerm terminal script to {wezterm_terminal_script_path}")
|
||||||
|
with open(wezterm_terminal_script_path, "w") as file:
|
||||||
|
file.write(wezterm_terminal_script)
|
||||||
|
|
||||||
|
# Create Odin work-around scripts
|
||||||
|
# Odin uses J. Blow's Microsoft craziness SDK locator which relies on the
|
||||||
|
# registry. Here we inject the registry entry that the SDK locator checks for
|
||||||
|
# finding our portable MSVC installation.
|
||||||
|
win10_sdk_find_test_dir_reg_path = str(win10_sdk_find_test_dir).replace("\\", "\\\\")
|
||||||
|
odin_msvc_install_script = f"""Windows Registry Editor Version 5.00
|
||||||
|
|
||||||
|
[HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows Kits\Installed Roots]
|
||||||
|
"KitsRoot10"="{win10_sdk_find_test_dir_reg_path}"
|
||||||
|
"""
|
||||||
|
|
||||||
|
odin_msvc_uninstall_script = f"""Windows Registry Editor Version 5.00
|
||||||
|
|
||||||
|
[HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows Kits\Installed Roots]
|
||||||
|
"KitsRoot10"=-
|
||||||
|
"""
|
||||||
|
|
||||||
|
odin_msvc_install_script_path = devenver.base_install_dir / "odin_msvc_install_workaround.reg"
|
||||||
|
odin_msvc_uninstall_script_path = devenver.base_install_dir / "odin_msvc_uninstall_workaround.reg"
|
||||||
|
|
||||||
|
devenver.lprint(f"Installing Odin MSVC workaround scripts", level=0)
|
||||||
|
devenver.lprint(f" - {odin_msvc_install_script_path}", level=1)
|
||||||
|
devenver.lprint(f" - {odin_msvc_uninstall_script_path}", level=1)
|
||||||
|
|
||||||
|
with open(odin_msvc_install_script_path, "w") as file:
|
||||||
|
file.write(odin_msvc_install_script)
|
||||||
|
|
||||||
|
with open(odin_msvc_uninstall_script_path, "w") as file:
|
||||||
|
file.write(odin_msvc_uninstall_script)
|
||||||
|
|
||||||
|
# Add python-update bootstrap script
|
||||||
|
# TODO: If I'm using the terminal that this script generates it will lock the
|
||||||
|
# executable and Python cannot open the file for verifying the SHA256.
|
||||||
|
|
||||||
|
python_exe = pathlib.Path(installed_apps["Python"][0]['exe_path']).relative_to(devenver.base_install_dir)
|
||||||
|
python_install_dir = pathlib.Path(installed_apps["Python"][0]['exe_path']).parent.relative_to(devenver.base_install_dir)
|
||||||
|
win_setup_script_path = pathlib.Path(devenver.script_dir, "win_setup.py")
|
||||||
|
manifest_script_path = pathlib.Path(devenver.script_dir, "devenver_manifest.py")
|
||||||
|
|
||||||
|
bootstrap_setup_script = f"""@echo off
|
||||||
|
setlocal EnableDelayedExpansion
|
||||||
|
set PYTHONHOME=%~dp0{python_install_dir}
|
||||||
|
%~dp0{python_exe} {win_setup_script_path} --manifest-file {manifest_script_path}
|
||||||
|
pause
|
||||||
|
"""
|
||||||
|
|
||||||
|
with open(devenver.base_install_dir / "upgrade_bootstrap.bat", "w") as file:
|
||||||
|
file.write(bootstrap_setup_script)
|
Loading…
Reference in New Issue
Block a user