I have a variable declared in .bzl file example: VERSION_NUMBER = "00".
I want to override this variable from command line when i build different version of the project.
example: bazel build target --sunbversion_number= "99"
I want to change this variable because it is invoked in some function to create the name of the output paths.
exammple: for version "00" the outputfile will be: name_00.extension
and for version "99" the outputfile will be: name_99.extension
This is my example:
in .bzl file i declared:
SUBVERSION_NUMBER = "99"
and a fucntion that return a name of the file regarding to the SUBVERSION_NUMBER
def get_name(SUBVERSION_NUMBER):
return "test-"+SUBVERSION_NUMBER
OUTPUT_NAME = get_name("99")
Then my genrule():
genrule(name = "test",
srcs = [srcs],
outs = [OUTPUT_NAME+".tek"],
cmd = "cmd to generate the file" )
when i build this rule i get the output file test-99.tek
what i want is when i run bazel build test --//version=01 or any other suggested solution, i want to get output test-01.tek
Thanks
There is no way to get values from the command line into a bzl file like that, but there are a few options, depending on exactly what you want to do.
One way is to use "stamping" to set the version, and then put the versioned file in a zip file with a known name, e.g. using a genrule. Build stamping is usually used for embedding a version number and other information into the output files themselves, but can be used here too. A zip file is necessary because the output file name has to be known at load time (i.e. before any configuration data from the command line is processed at analysis time).
Something like this:
# out.txt is the original unversioned file
genrule(
name = "gen_out",
outs = ["out.txt"],
cmd = "echo foo > $#",
)
genrule(
name = "gen_versioned_out",
outs = ["out_versioned.zip"],
srcs = [":out.txt"],
tools = ["#bazel_tools//tools/zip:zipper"],
stamp = True,
cmd = """
# bazel-out/stable-status.txt is created when stamp = True
# Value of BUILD_EMBED_LABEL key comes from --embed_label on the command line
version="$$(grep BUILD_EMBED_LABEL bazel-out/stable-status.txt | cut -d ' ' -f 2)"
# Set a reasonable default if --embed_label was not specified
if [ -z "$$version" ]; then version="0"; fi
file="$$(basename $<)"
name="$${file%%.*}"
ext="$${file#*.}"
versioned_file="$${name}_$${version}.$${ext}"
# zipper allows specifying the name of the file in the zip directly, unlike the
# regular zip tool.
# c = create
# $# = output file from "outs"
# $< = input file from "srcs"
# $$versioned_file=$< = "put this file in to the archive with this name"
$(location #bazel_tools//tools/zip:zipper) c "$#" "$$versioned_file=$<"
""",
)
Then:
$ bazel build out_versioned.zip --embed_label=99
INFO: Analyzed target //:out_versioned.zip (7 packages loaded, 19 targets configured).
INFO: Found 1 target...
Target //:out_versioned.zip up-to-date:
bazel-bin/out_versioned.zip
INFO: Elapsed time: 0.340s, Critical Path: 0.10s
INFO: 3 processes: 1 internal, 2 linux-sandbox.
INFO: Build completed successfully, 3 total actions
$ unzip -l bazel-bin/out_versioned.zip
Archive: bazel-bin/out_versioned.zip
Length Date Time Name
--------- ---------- ----- ----
4 2010-01-01 00:00 out_99.txt
--------- -------
4 1 file
So that results in a zip file with a known name containing the versioned file.
Another approach is to use "User-defined build settings":
https://docs.bazel.build/versions/master/skylark/config.html#user-defined-build-settings
Something like this:
defs.bzl:
def _version_file_impl(ctx):
version = ctx.attr._version[VersionProvider].version
name, extension = ctx.file.file.basename.rsplit(".", 1)
versioned_file = ctx.actions.declare_file(
"%s_%s.%s" % (name, version, extension))
copy_args = ctx.actions.args()
copy_args.add_all([ctx.file.file, versioned_file])
ctx.actions.run_shell(
inputs = [ctx.file.file],
outputs = [versioned_file],
command = 'cp "$1" "$2"',
arguments = [copy_args])
return DefaultInfo(files = depset([versioned_file]))
version_file = rule(
implementation = _version_file_impl,
attrs = {
"file": attr.label(mandatory = True, allow_single_file = True),
"_version": attr.label(default = "//:version"),
}
)
VersionProvider = provider(fields = ["version"])
def _version_flag_impl(ctx):
return VersionProvider(version = ctx.build_setting_value)
version_flag = rule(
implementation = _version_flag_impl,
build_setting = config.int(flag = True),
)
BUILD:
load(":defs.bzl", "version_flag", "version_file")
version_flag(
name = "version",
build_setting_default = 0,
)
genrule(
name = "gen_out",
outs = ["out.txt"],
cmd = "echo foo > $#",
)
version_file(
name = "versioned_out",
file = ":out.txt",
)
Then:
$ bazel build :versioned_out --//:version=99
INFO: Analyzed target //:versioned_out (5 packages loaded, 10 targets configured).
INFO: Found 1 target...
Target //:versioned_out up-to-date:
bazel-bin/out_99.txt
INFO: Elapsed time: 0.322s, Critical Path: 0.06s
INFO: 3 processes: 1 internal, 2 linux-sandbox.
INFO: Build completed successfully, 3 total actions
So that results in a file with the version in its name. There's no label to refer to the versioned file itself though, so bazel build :out_99.txt nor srcs = [":out_99.txt"] will work, you have to go through the versioned_out target.
Update:
Here's a version that can version multiple outputs:
defs.bzl:
def _versioned_files_impl(ctx):
version = ctx.attr._version[VersionProvider].version
versioned_files = []
for f in ctx.attr.src.files.to_list():
name, extension = f.basename.rsplit(".", 1)
versioned_file = ctx.actions.declare_file(
"%s_%s.%s" % (name, version, extension))
versioned_files.append(versioned_file)
copy_args = ctx.actions.args()
copy_args.add_all([f, versioned_file])
ctx.actions.run_shell(
inputs = [f],
outputs = [versioned_file],
command = 'cp "$1" "$2"',
arguments = [copy_args])
return DefaultInfo(files = depset(versioned_files))
versioned_files = rule(
implementation = _versioned_files_impl,
attrs = {
"src": attr.label(mandatory = True),
"_version": attr.label(default = "//:version"),
}
)
VersionProvider = provider(fields = ["version"])
def _version_flag_impl(ctx):
return VersionProvider(version = ctx.build_setting_value)
version_flag = rule(
implementation = _version_flag_impl,
build_setting = config.int(flag = True),
)
BUILD:
load(":defs.bzl", "version_flag", "versioned_files")
version_flag(
name = "version",
build_setting_default = 0,
)
genrule(
name = "gen_out",
outs = ["foo.txt", "bar.txt", "baz.txt"],
cmd = """
echo foo > $(location foo.txt)
echo bar > $(location bar.txt)
echo baz > $(location baz.txt)
""",
)
versioned_files(
name = "versioned_files",
src = ":gen_out",
)
usage:
$ bazel build versioned_files --//:version=123
INFO: Analyzed target //:versioned_files (5 packages loaded, 9 targets configured).
INFO: Found 1 target...
Target //:versioned_files up-to-date:
bazel-bin/foo_123.txt
bazel-bin/bar_123.txt
bazel-bin/baz_123.txt
INFO: Elapsed time: 0.491s, Critical Path: 0.06s
INFO: 5 processes: 1 internal, 4 linux-sandbox.
INFO: Build completed successfully, 5 total actions
Update:
An example of putting the version in a cc target's define:
BUILD:
cc_binary(
name = "main",
srcs = ["main.cc"],
defines = ["VERSION=\\\"$(VERSION)\\\""],
)
main.cc:
#include <iostream>
#ifndef VERSION
#define VERSION "0.0.0"
#endif
int main() {
std::cout << "version: " << VERSION << std::endl;
return 0;
}
build and run:
$ bazel run main --define=VERSION=1.2.3
INFO: Analyzed target //:main (15 packages loaded, 52 targets configured).
INFO: Found 1 target...
Target //:main up-to-date:
bazel-bin/main
INFO: Elapsed time: 0.524s, Critical Path: 0.26s
INFO: 6 processes: 4 internal, 2 linux-sandbox.
INFO: Build completed successfully, 6 total actions
INFO: Build completed successfully, 6 total actions
version: 1.2.3
Combining the above methods, you would have to specify both --//:version=1.2.3 and --define=VERSION=1.2.3 on the command line. There's a way to have only --//:version, but it would require another Starlark rule like versioned_files which either
generates a file with the version in it that goes in the data attribute and the program reads at runtime, or
a Starlark rule which generates a C++ file with the version in it, which then gets put in the sources of a cc_library, which the rest of your program can depend on and use at compile time.
These approaches will probably require refactoring your program.
Related
Assuming I have a cc_binary() rule like this:
cc_binary(
name = "App",
srcs = [
"app.cpp",
],
)
This will produce App.exe somewhere in bazel-bin. I need to write a genrule that can read App.exe and produce another version of it. How can I do that?
Edit: this is my current attempt for a genrule, but it forces the recompilation of :hello_main with a different configuration and I end up getting errors like "error C2955: 'std::pair': use of class template requires template argument list"
genrule(
name = "tbds",
srcs = [
":data",
],
outs = ["tbds.exe"],
exec_tools = ["#libpackfiles//FilePacker"],
tools = [":hello_main"],
cmd = "cp $(location :hello_main) $(OUTS) && $(location #libpackfiles//FilePacker) $(OUTS) -files $(SRCS) -append",
executable = true,
)
cc_binary(
name = "hello_main",
srcs = ["hello_main.cc"],
deps = [
":hello",
],
)
genrule(
name = "foo",
outs = ["out.txt"],
cmd = "du -sh $(location :hello_main)` > $#",
tools = [":hello_main"],
visibility = ["//visibility:public"],
)
will create a out.txt file with an output of a du -sh command. You can add an another tool to a tools attribute to run some transforming script on your binary
I am trying to edit and run a snakemake pipeline. In a nutshell, the snakemake pipeline calls a default genome aligner (minimap) and produces output files with this name. I am trying to add a variable aligner to config.yaml to specify the aligner I want to call. Also (where I am actually stuck), the output files should have the name of the aligner specified in config.yaml.
My config.yaml looks like this:
# this config.yaml is passed to Snakefile in pipeline-structural-variation subfolder.
# Snakemake is run from this pipeline-structural-variation folder; it is necessary to
# pass an appropriate path to the input-files (the ../ prefix is sufficient for this demo)
aligner: "ngmlr" # THIS IS THE VARIABLE I AM ADDING TO THIS FILE. VALUES COULD BE minimap or ngmlr
# FASTQ file or folder containing FASTQ files
# check if this has to be gzipped
input_fastq: "/nexusb/Gridion/20190917PGD2staal2/PD170815/PD170815_cat_all.fastq.gz" # original is ../RawData/GM24385_nf7_chr20_af.fastq.gz
# FASTA file containing the reference genome
# note that the original reference sequence contains only the sequence of chr20
reference_fasta: "/nexus/bhinckel/19/ONT_projects/PGD_breakpoint/ref_hg19_local/hg19_chr1-y.fasta" # original is ../ReferenceData/human_g1k_v37_chr20_50M.fasta
# Minimum SV length
min_sv_length: 300000 # original value was 40
# Maximum SV length
max_sv_length: 1000000 # original value was 1000000. Note that the value I used to run the pipeline for the sample PD170677 was 100000000000, which will be coerced to NA in the R script (/home/bhinckel/ont_tutorial_sv/ont_tutorial_sv.R)
# Min read length. Shorter reads will be discarded
min_read_length: 1000
# Min mapping quality. Reads will lower mapping quality will be discarded
min_read_mapping_quality: 20
# Minimum read support required to call a SV (auto for auto-detect)
min_read_support: 'auto'
# Sample name
sample_name: "PD170815" # original value was GM24385.nf7.chr20_af. Note that this can be a list
I am posting below the sections of my snakefile which generate output files with the extension _minimap2.bam, which I would like to replace by either _minimap2.bam or _ngmlr.bam, depending on aligner on config.yaml
# INPUT BAM folder
bam = None
if "bam" in config:
bam = os.path.join(CONFDIR, config["bam"])
# INPUT FASTQ folder
FQ_INPUT_DIRECTORY = []
if not bam:
if not "input_fastq" in config:
print("\"input_fastq\" not specified in config file. Exiting...")
FQ_INPUT_DIRECTORY = os.path.join(CONFDIR, config["input_fastq"])
if not os.path.exists(FQ_INPUT_DIRECTORY):
print("Could not find {}".format(FQ_INPUT_DIRECTORY))
MAPPED_BAM = "{sample}/alignment/{sample}_minimap2.bam" # Original
#MAPPED_BAM = "{sample}/alignment/{sample}_{alignerName}.bam" # this did not work
#MAPPED_BAM = f"{sample}/alignment/{sample}_{config['aligner']}.bam" # this did nor work either
else:
MAPPED_BAM = find_file_in_folder(bam, "*.bam", single=True)
...
if config['aligner'] == 'minimap':
rule index_minimap2:
input:
REF = FA_REF
output:
"{sample}/index/minimap2.idx"
threads: config['threads']
conda: "env.yml"
shell:
"minimap2 -t {threads} -ax map-ont --MD -Y {input.REF} -d {output}"
rule map_minimap2:
input:
FQ = FQ_INPUT_DIRECTORY,
IDX = rules.index_minimap2.output,
SETUP = "init"
output:
BAM = "{sample}/alignment/{sample}_minimap2.bam",
BAI = "{sample}/alignment/{sample}_minimap2.bam.bai"
conda: "env.yml"
threads: config["threads"]
shell:
"cat_fastq {input.FQ} | minimap2 -t {threads} -K 500M -ax map-ont --MD -Y {input.IDX} - | samtools sort -# {threads} -O BAM -o {output.BAM} - && samtools index -# {threads} {output.BAM}"
else:
print(f"Aligner is {config['aligner']} - skipping indexing step for minimap2")
rule map_ngmlr:
input:
REF = FA_REF,
FQ = FQ_INPUT_DIRECTORY,
SETUP = "init"
output:
BAM = "{sample}/alignment/{sample}_minimap2.bam",
BAI = "{sample}/alignment/{sample}_minimap2.bam.bai"
conda: "env.yml"
threads: config["threads"]
shell:
"cat_fastq {input.FQ} | ngmlr -r {input.REF} -t {threads} -x ont - | samtools sort -# {threads} -O BAM -o {output.BAM} - && samtools index -# {threads} {output.BAM}"
I initially tried to create a alignerName parameter, similar to the sample parameter, as shown below:
# Parameter: sample_name
sample = "sv_sample01"
if "sample_name" in config:
sample = config['sample_name']
###############
#
# code below created by me
#
###############
# Parameter: aligner_name
alignerName = "defaultAligner"
if "aligner" in config:
alignerName = config['aligner']
Then I tried to input {alignerName} wherever I have minimap2 on my input/ output files (see commented MAPPED_BAM variable definition above), though this is throwing an error. I guess snakemake will interpret {alignerName} as a wildcard, though what I want is simply to pass the variable name defined in config['aligner'] to input/ output files. I also tried with f-string (MAPPED_BAM = f"{sample}/alignment/{sample}_{config['aligner']}.bam"), though I guess this it did not work either.
You are close!
The way wildcards work in snakemake is they get interpreted 'last', while f-strings get interpreted first. To not interpret a curly brace in an f-string you can escape it with another curly brace, like so:
print(f"{{keep curly}}")
>>> {keep curly}
So all we need to do is
MAPPED_BAM = f"{{sample}}/alignment/{{sample}}_{config['aligner']}.bam"
I'm trying to improve on the original solution (INI file parsing in PowerShell) so I can parse an INI file with entries like the example below.
[proxy]
; IP address and port number
server = 192.168.0.253
port = 8080
logfile=session.log ; log session
[user]
; default username and settings
name=J. Doe ;name
address="377 Sunrise Way;Santa Monica;CA" ; address
[program files]
root="C:\Program Files\Windows " ; path name
path="C:\Program Files\Windows;%windir" ; path name
;
[program]
root=C:\Program Files\Windows ; path name
path=C:\Program Files\Windows;%windir ; path name
I'm using the following powershell code to populate a nested hash table (if that is the right description) containing the name/value pairs for each section.
I have no problem dealing with the first section where I have lines ending in a comment, or with the value in the second section which contains spaces, but things go wrong when I try to mix quoted strings and comments.
Given that a string begins and ends with a double quote I think it should be possible to get the results I want but I am obviously missing something somewhere (I am a little new to this).
function Parse-INI-File() {
Param ([parameter()][string]$_file = '')
# Don't prompt to continue if '-Debug' is specified.
If ($DebugPreference -eq "Inquire") {$DebugPreference = "Continue"}
$_settings=#{}
switch -Regex -file $_file {
'(?:^ ?\[\s*(?<section>[^\s]+[^#;\r\n\[\]]+)\s*\])' {
$_section = $Matches.section.trim()
$_settings[$_section] = #{}
}
'(?:^\s*?(?<name>[^\[\]\r\n=#;]+))(?: ?=\s*"?(?<value>[^;#\\\r\n]*(?:\\.[^"#\\\r\n]*)*))' {
$_name, $_value = $Matches.name.trim(), $matches.value.trim()
$_settings[$_section][$_name] = $_value
Write-Debug "/$_section/ /$_name//$_value/" # Debug
}
}
$_settings
}
$_file='./ini-example.ini'
$_output=Parse-INI-File -Debug ($_file)
What I'd like is for the parsing of the sample ini file to result in the following name/value pairs:
DEBUG: /proxy/ /server//192.168.0.253/
DEBUG: /proxy/ /port//8080/
DEBUG: /proxy/ /logfile//session.log/
DEBUG: /user/ /name//J. Doe/
DEBUG: /user/ /address//377 Sunrise Way;Santa Monica;CA/
DEBUG: /program files/ /root//C:\Program Files\Windows/
DEBUG: /program files/ /path//C:\Program Files\Windows;%windir/
DEBUG: /program/ /root//C:\Program Files\Windows/
DEBUG: /program/ /path//C:\Program Files\Windows/
I don't mind if quoted strings include the original quotes or not.
Thank you.
Updated 10 Sep 19 - I have tried the Get-IniContent function in the psini module, but it doesn't ignore comments at the end of a line.
PS C:\> $_output = Get-IniContent (".\ini-example.ini")
PS C:\> $_output["program files"]
Name Value
---- -----
root "C:\Program Files\Windows "' ; path name
path "C:\Program Files\Windows;;%windir" ; path name
Comment1 ;
PS C:\>
Think I've solved it, there is probably a better solution but I solved the problem by using a separate regex for quoted strings - this complicates the logic a bit but seems to solve the problem reliably.
function Parse-INI-File() {
Param ([parameter()][string]$_file = '')
# Don't prompt to continue if '-Debug' is specified.
If ($DebugPreference -eq "Inquire") {$DebugPreference = "Continue"}
$_settings=#{}
switch -Regex -file $_file {
'(?:^ ?\[\s*(?<section>[^\s]+[^\r\n\[\]]+)\s*\])' {
$_section = $Matches.section.trim()
$_settings[$_section] = #{}
#Write-Debug "1/$_section/" # Debug
}
'(?:^\s*?(?<name>[^\[\]\r\n]+))(?: ?=\s*(?<value>[^";#\\\r\n]*(?:\\.[^";#\\\r\n]*)*))' {
If ($matches.value -ne '' ) {
$_name, $_value = $Matches.name.trim(), $matches.value.trim()
$_settings[$_section][$_name] = $_value
Write-Debug "2/$_section//$_name//$_value/" # Debug
}
}
'(?:^\s*?(?<name>[^\[\]\r\n]+))(?: ?=\s*(?<value>\"+[^\"\r\n]*\")*)' {
#If ($matches.value -ne $null ) {
If (-not [string]::IsNullOrEmpty($matches.value)) {
$_name, $_value = $Matches.name.trim(), $matches.value.trim()
$_settings[$_section][$_name] = $_value
Write-Debug "3/$_section//$_name//$_value/" # Debug
}
}
}
$_settings
}
This seems to produces the results I'd expect
PS C:\> $_output = Parse-INI-File -Debug (".\ini-example.ini")
DEBUG: 2/proxy//server//192.168.0.253/
DEBUG: 2/proxy//port//8080/
DEBUG: 2/proxy//logfile//session.log/
DEBUG: 2/user//name//J. Doe/
DEBUG: 3/user//address//"377 Sunrise Way;Santa Monica;CA"/
DEBUG: 3/program files//root//"C:\Program Files\Windows "/
DEBUG: 3/program files//path//"C:\Program Files\Windows;%windir"/
DEBUG: 2/program//root//C:\Program Files\Windows/
DEBUG: 2/program//path//C:\Program Files\Windows/
PS C:\> $_output["user"]
Name Value
---- -----
name J. Doe
address "377 Sunrise Way;Santa Monica;CA"
PS C:\>
Note that if there are multiple values with the same name in a section then only the last value is returned (try parsing system.ini to see what I mean)
I am trying to use OpenSSL but I am stuck on the step of compiling. The OpenSSL project has very unfriendly (bad) documentation.
Is there any actual help how to build the latest OpenSSL version on Windows with Visual Studio 2017?
I didn't find any helpful information on the official OpenSSL site. Yes, there are a lot of posts on the Internet about OpenSSL compilation, but all of them are obsolete.
I've not used VS2017 but previous versions. I imagine it is much the same. Note the instructions below are for OpenSSL 1.1.0 or above. They do not work for OpenSSL 1.0.2. In brief the steps are:
Install Perl (either ActiveState or Strawberry)
[EDIT, see my (kritzel_sw) comment below: I would strongly recommend to use Strawberry)]
Install NASM
Make sure both Perl and NASM are on your %PATH%
Fire up a Visual Studio Developer Command Prompt with administrative privileges (make sure you use the 32-bit one if you are building 32-bit OpenSSL, or the 64-bit one if you are building 64-bit OpenSSL)
From the root of the OpenSSL source directory enter perl Configure VC-WIN32, if you want 32-bit OpenSSL or perl Configure VC-WIN64A if you want 64-bit OpenSSL
Enter nmake
Enter nmake test
Enter nmake install
[EDIT, unless you change the target directory in the configuration, nmake install needs administrator privileges. So the VC command prompt must be started as administrator for this final step]
If anything goes wrong at any stage, check the INSTALL file and the NOTES.WIN file.
Modified version of The Quantum Physicist python script
It can compile OpenSSL 1.0.x or OpenSSL 1.1.x
It can compile with multiple version of Visual Studio 2017/2019 included.
1) Create the file: CompileOpenSSL.py
import os
import os.path
from subprocess import call
import shutil
import sys
import re
import argparse
# args
parser = argparse.ArgumentParser()
parser.add_argument("-f", "--filename", help="First argument must be the tar.gz file of OpenSSL source", required=True)
parser.add_argument("-a", "--arch", help="Second argument must be x86 or amd64", required=True)
parser.add_argument("-v", "--vs_version", help="Visual Studio version (eg:90, 140, 150)", required=True)
parser.set_defaults(writeVersionInfos=False)
args = parser.parse_args()
compile_flags = "-no-asm"
#compile_flags = "-no-asm -no-shared"
openssl_32_flag = "VC-WIN32"
openssl_64_flag = "VC-WIN64A"
working_dir = os.getcwd()
dirname = args.filename.replace(".tar.gz","")
src_32_suffix = "_" + "vs" + args.vs_version + "_32"
src_64_suffix = "_" + "vs" + args.vs_version + "_64"
vs_tools_env_var = "VS" + args.vs_version + "COMNTOOLS"
if args.arch != "x86" and args.arch != "amd64":
print("Second argument must be x86 or amd64")
exit(1)
if not bool(re.match("(openssl-){1}(\d)+(.)(\d)+(.)(\d)+(\w)+(.tar.gz)",args.filename)):
print("The file given doesn't seem to be an openssl source file. It must be in the form: openssl-x.y.zw.tar.gz")
exit(1)
call("7z x -y " + args.filename) #extract the .gz file
dirname_src_32 = dirname + src_32_suffix
dirname_src_64 = dirname + src_64_suffix
dirname_bin_32 = dirname + src_32_suffix + "_build"
dirname_bin_64 = dirname + src_64_suffix + "_build"
openssl_tar_file = args.filename[0:-3]
if args.arch == "x86":
#delete previous directories
shutil.rmtree(os.getcwd()+'/'+dirname, ignore_errors=True)
shutil.rmtree(os.getcwd()+'/'+dirname_src_32, ignore_errors=True)
#extract tar file for 32
call("7z x -y " + openssl_tar_file)
os.rename(dirname, dirname_src_32)
#Compile 32
os.chdir(dirname_src_32)
print("perl Configure " + openssl_32_flag + " --prefix=" + os.path.join(working_dir,dirname_bin_32) + " " + compile_flags)
call("perl Configure " + openssl_32_flag + " --prefix=" + os.path.join(working_dir,dirname_bin_32) + " " + compile_flags,shell=True)
if( os.path.exists("ms/do_ms.bat") ):
call("ms\do_ms.bat",shell=True)
print(os.getcwd())
call("nmake -f ms/ntdll.mak",shell=True)
call("nmake -f ms/ntdll.mak install",shell=True)
else:
call("nmake",shell=True)
call("nmake test",shell=True)
call("nmake install",shell=True)
print("32-bit compilation complete.")
#Go back to base dir
os.chdir(working_dir)
################
if args.arch == "amd64":
#delete previous directories
shutil.rmtree(os.getcwd()+'/'+dirname, ignore_errors=True)
shutil.rmtree(os.getcwd()+'/'+dirname_src_64, ignore_errors=True)
#extract for 64
call("7z x -y " + openssl_tar_file)
os.rename(dirname, dirname_src_64)
#Compile 64
os.chdir(dirname_src_64)
call("perl Configure " + openssl_64_flag + " --prefix=" + os.path.join(working_dir,dirname_bin_64) + " " + compile_flags,shell=True)
if( os.path.exists("ms\do_ms.bat") ):
call("ms\do_win64a.bat",shell=True)
call("nmake -f ms/ntdll.mak",shell=True)
call("nmake -f ms/ntdll.mak install",shell=True)
else:
call("nmake",shell=True)
call("nmake test",shell=True)
call("nmake install",shell=True)
print("64-bit compilation complete.")
#Go back to base dir
os.chdir(working_dir)
################
os.remove(openssl_tar_file)
2) Create the file: CompileOpenSSL_vs.cmd
ECHO --------------------------------------
ECHO Require Python, 7Zip, PERL and NASM in PATH
ECHO --------------------------------------
Rem ------------------------------------------------------
Rem TO CONFIGURE -----------------------------------------
Rem ------------------------------------------------------
Rem SET YOUR LOCAL PATHS-----------------------------------------
SET PATH=C:\Program Files (x86)\7-Zip;C:\Perl64\bin;M:\Backup\Coders\_tools\7-Zip\;%PATH%
Rem SET YOUR OPENSSL ARCHIVE-----------------------------------------
REM SET FILENAME=openssl-1.0.2r.tar.gz
SET FILENAME=openssl-1.1.1b.tar.gz
Rem SET THE VERSION OF YOUR VISUAL STUDIO-----------------------------------------
SET VSVERSION=%1
Rem ------------------------------------------------------
Rem COMPILATION LAUNCH -----------------------------------
Rem ------------------------------------------------------
Rem UTILS PATH-----
SET VSCOMNTOOLSNAME=VS%VSVERSION%COMNTOOLS
Rem Pick the good path for Visual Studio-----------------------------------------
IF %VSVERSION% GEQ 150 (
Echo DO NOT FORGET TO ADD A SYSTEM VARIABLE %VSCOMNTOOLSNAME% - like: "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\Tools\"
SET VCVARPATH="%%%VSCOMNTOOLSNAME%%%..\..\VC\Auxiliary\Build\vcvarsall.bat"
) ELSE (
SET VCVARPATH="%%%VSCOMNTOOLSNAME%%%..\..\VC\vcvarsall.bat"
)
Rem Set env -----------------------------------------
#pushd "%~dp0"
call %VCVARPATH% %2
#popd
Rem ------------------------------------------------------
Rem TEST APP EXIST -----------------------------------
Rem ------------------------------------------------------
where /q 7z.exe
IF ERRORLEVEL 1 (
ECHO The application "7z.exe" is missing. Ensure to add/install it to the PATH in beginning of this script, check SET PATH
PAUSE
EXIT /B
)
where /q perl.exe
IF ERRORLEVEL 1 (
ECHO The application "perl.exe" is missing. Ensure to add/install it to the PATH in beginning of this script, check SET PATH
PAUSE
EXIT /B
)
where /q nmake.exe
IF ERRORLEVEL 1 (
ECHO The application "nmake.exe" is missing. Ensure to add/install it to the PATH in beginning of this script, check SET PATH
PAUSE
EXIT /B
)
where /q py.exe
IF ERRORLEVEL 1 (
ECHO The application "py.exe" [shortcut of python] is missing. Ensure to add/install it to the PATH in beginning of this script, check SET PATH
PAUSE
EXIT /B
)
Rem Launch compilation -----------------------------------------
py CompileOpenSSL.py -f %FILENAME% -a %2 -v %VSVERSION%
PAUSE
3) Launch compilation from command line (Outside Visual Studio)
eg:
CompileOpenSSL_vs.cmd 150 x86
CompileOpenSSL_vs.cmd 150 amd64
CompileOpenSSL_vs.cmd 90 x86
For OpenSSL 1.0.2, I wrote a Python script that does the building for me. I have this habit of making these scripts, as I don't like to reinvent the wheel everytime I need to build something.
The script is made for OpenSSL 1.0.2. Probably the changes are minimal for OpenSSL 1.1.0.
Here's the script:
import os
from subprocess import call
import sys
import re
vs_version = "140"
compile_flags = "-no-asm -no-shared"
openssl_32_flag = "VC-WIN32"
openssl_64_flag = "VC-WIN64A"
src_32_suffix = "_" + "vs" + vs_version + "_32"
src_64_suffix = "_" + "vs" + vs_version + "_64"
vs_tools_env_var = "VS" + vs_version + "COMNTOOLS"
if len(sys.argv) < 2:
print("First argument must be the tar.gz file of OpenSSL source")
exit(1)
if len(sys.argv) < 3:
print("Second argument must be 32 or 64")
exit(1)
filename = sys.argv[1]
dirname = filename.replace(".tar.gz","")
working_dir = os.getcwd()
arch = sys.argv[2]
if arch != "32" and arch != "64":
print("Second argument must be 32 or 64")
exit(1)
if not bool(re.match("(openssl-){1}(\d)+(.)(\d)+(.)(\d)+(\w)+(.tar.gz)",filename)):
print("The file given doesn't seem to be an openssl source file. It must be in the form: openssl-x.y.zw.tar.gz")
exit(1)
call("7z x " + filename) #extract the .gz file
dirname_src_32 = dirname + src_32_suffix
dirname_src_64 = dirname + src_64_suffix
dirname_bin_32 = dirname + src_32_suffix + "_build"
dirname_bin_64 = dirname + src_64_suffix + "_build"
openssl_tar_file = filename[0:-3]
if arch == "32":
#extract tar file for 32
call("7z x " + openssl_tar_file)
os.rename(dirname, dirname_src_32)
#Compile 32
os.chdir(dirname_src_32)
call("perl Configure " + openssl_32_flag + " --prefix=" + os.path.join(working_dir,dirname_bin_32) + " " + compile_flags,shell=True)
call(r"ms\do_ms.bat",shell=True)
call(r"nmake -f ms\nt.mak",shell=True)
call(r"nmake -f ms\nt.mak instalL",shell=True)
print("32-bit compilation complete.")
#Go back to base dir
os.chdir(working_dir)
################
if arch == "64":
#extract for 64
call("7z x " + openssl_tar_file)
os.rename(dirname, dirname_src_64)
#Compile 64
os.chdir(dirname_src_64)
call("perl Configure " + openssl_64_flag + " --prefix=" + os.path.join(working_dir,dirname_bin_64) + " " + compile_flags,shell=True)
call(r"ms\do_ms.bat",shell=True)
call(r"nmake -f ms\nt.mak",shell=True)
call(r"nmake -f ms\nt.mak instalL",shell=True)
print("64-bit compilation complete.")
#Go back to base dir
os.chdir(working_dir)
################
os.remove(openssl_tar_file)
Option 1: Save the script to CompileOpenSSL.py, and download the OpenSSL source file that is expected to have the name format openssl-1.X.Y.tar.gz. Now assuming that 7zip and perl are accessible from the global scope on your command prompt and you have the correct MSVC variables loaded (with e.g. vsvars32.bat, or starting the right terminal), run the following:
python CompileOpenSSL.py openssl-1.X.Y.tar.gz 32
If you're using MSVC 32-bit, or
python CompileOpenSSL.py openssl-1.X.Y.tar.gz 64
for MSVC 64-bit.
Option 2: Do what the script does manually. The script simply extracts the archive, configures the sources and runs do_ms.bat then nmake. Follow the source and it'll work.
Good luck!
go into ssl directory using visual studio cmd and add perl and nasm to system path then type:
perl Configure --openssldir=D:OpenSSLdirectory VC-WIN32
ms\do_ms.bat
nmake -f ms\ntdll.mak
nmake -f ms\ntdll.mak install
( enjoy. )
my .s3cfg with GPG encryption passphrase and other security settings. Would you recommend other security hardening?
[default]
access_key = $USERNAME
access_token =
add_encoding_exts =
add_headers =
bucket_location = eu-central-1
ca_certs_file =
cache_file =
check_ssl_certificate = True
check_ssl_hostname = True
cloudfront_host = cloudfront.amazonaws.com
default_mime_type = binary/octet-stream
delay_updates = False
delete_after = False
delete_after_fetch = False
delete_removed = False
dry_run = False
enable_multipart = True
encoding = UTF-8
encrypt = False
expiry_date =
expiry_days =
expiry_prefix =
follow_symlinks = False
force = False
get_continue = False
gpg_command = /usr/local/bin/gpg
gpg_decrypt = %(gpg_command)s -d --verbose --no-use-agent --batch --yes --passphrase-fd %(passphrase_fd)s -o %(output_file)s %(input_file)s
gpg_encrypt = %(gpg_command)s -c --verbose --no-use-agent --batch --yes --passphrase-fd %(passphrase_fd)s -o %(output_file)s %(input_file)s
gpg_passphrase = $PASSPHRASE
guess_mime_type = True
host_base = s3.amazonaws.com
host_bucket = %(bucket)s.s3.amazonaws.com
human_readable_sizes = False
invalidate_default_index_on_cf = False
invalidate_default_index_root_on_cf = True
invalidate_on_cf = False
kms_key =
limitrate = 0
list_md5 = False
log_target_prefix =
long_listing = False
max_delete = -1
mime_type =
multipart_chunk_size_mb = 15
multipart_max_chunks = 10000
preserve_attrs = True
progress_meter = True
proxy_host =
proxy_port = 0
put_continue = False
recursive = False
recv_chunk = 65536
reduced_redundancy = False
requester_pays = False
restore_days = 1
secret_key = $PASSWORD
send_chunk = 65536
server_side_encryption = False
signature_v2 = False
simpledb_host = sdb.amazonaws.com
skip_existing = False
socket_timeout = 300
stats = False
stop_on_error = False
storage_class =
urlencoding_mode = normal
use_https = True
use_mime_magic = True
verbosity = WARNING
website_endpoint = http://%(bucket)s.s3-website-%(location)s.amazonaws.com/
website_error =
website_index = index.html
I use this command to upload/sync my local folder to Amazon S3.
s3cmd -e -v put --recursive --dry-run /Users/$USERNAME/Downloads/ s3://dgtrtrtgth777
INFO: Compiling list of local files...
INFO: Running stat() and reading/calculating MD5 values on 15957 files, this may take some time...
INFO: [1000/15957]
INFO: [2000/15957]
INFO: [3000/15957]
INFO: [4000/15957]
INFO: [5000/15957]
INFO: [6000/15957]
INFO: [7000/15957]
INFO: [8000/15957]
INFO: [9000/15957]
INFO: [10000/15957]
INFO: [11000/15957]
INFO: [12000/15957]
INFO: [13000/15957]
INFO: [14000/15957]
INFO: [15000/15957]
I tested the encryption with Transmit GUI S3 Client and didn't get plain text files.
But I see the original filename. I wish to change the filename to a random value, but have local the original filename (mapping?). How can I do this?
What are downsides doing so if I need to restore the files? I use Amazon S3 only as a backup, in addition to my TimeMachine backup.
If you use "random" names, then it isn't sync.
If your only record on the filenames/mapping is local, it will be impossible to restore your backup in case of a local failure.
If you don't need all versions of your files I'd suggest putting everything in a (possibly encrypted) compressed tarball before uploading it.
Otherwise, you will have to write a small script that lists all files and individually does an s3cmd put specifying a random destination, where the mapping is appended to a log file, which should be the first thing you s3cmd put to your server. I don't recommend this for something as crucial as storing your backups.
A skeleton showing how this could work:
# Save all files in backupX.sh where X is the version number
find /Users/$USERNAME/Downloads/ | awk '{print "s3cmd -e -v put "$0" s3://dgtrshitcrapola/"rand()*1000000}' > backupX.sh
# Upload the mapping file
s3cmd -e -v put backupX.sh s3://dgtrshitcrapola/
# Upload the actual files
sh backupX.sh
# Add cleanup code here
However, you will need to handle filename collisions, failed uploads, versioning clashes, ... why not use an existing tool that backs up to S3?