Skip to content

Instantly share code, notes, and snippets.

@ssfang
Last active May 15, 2017 01:54
Show Gist options
  • Save ssfang/d70574ba4746f6dd0700f61ed906a90b to your computer and use it in GitHub Desktop.
Save ssfang/d70574ba4746f6dd0700f61ed906a90b to your computer and use it in GitHub Desktop.
OpenSSL build on windows.

CMake 3.6 Documentation中,以命令行工具、GUI互动对话框、方法参考手册等方面介绍CMake。下面从自身脚本语法和配置工程两个方面了解CMake,但在这之前先熟悉一下如何执行脚本。

CMake命令行纲要

cmake [<options>] (<path-to-source> | <path-to-existing-build>)
cmake [(-D <var>=<value>)...] -P <cmake-script-file>
cmake --build <dir> [<options>...] [-- <build-tool-options>...]
cmake -E <command> [<options>...]
cmake --find-package <options>...

这里主要介绍下列选项,其他详见官方手册。

  • 第二行语义表示执行一个CMake语法的脚本文件
    -D <var>:<type>=<value>, -D <var>=<value> 可选的,创建缓存变量。
    -P <cmake-script-file> 必须的,指定所需执行的脚本文件;如果使用了-D,则必须在-P之前指定。
    

从CMake脚本开始

注释以#为开始的。其他操作(赋值、比较等)全是以命令方式来执行的。 格式COMMAND(arg1, arg2, ...),命令不区分大小写,命令每个参数均以空格,或者分号分割。

HelloWorld

set(who "World!")
message("Hello ${who}")

脚本名字一般xx.cmake比较好认,参考C:\Program Files\CMake\share\cmake-3.6\Modules下的脚本,如FindOpenSSL.cmake,将其命名为Hello.cmake。
执行:cmake -P Hello.cmake 输出:Hello world!

常用命令

  • 变量 无需声明,没有类型(只有字符串或字符串列表),区分大小写,作用域为脚本全局,在构建树会传播到子目录但不会污染父目录。
  • 赋值命令 SET
    set(<variable> <value>... [PARENT_SCOPE])
    set(<variable> <value1> ... <valueN>): <variable> is set to a semicolon separated list of values. set var as ;list
set(var "hello world!")
message(${var})
message("${var}")

set(var hello "world!")
message(${var})
message("${var}")
message(hello world!)

执行后输出:

hello world!
hello world!
helloworld!
hello;world!
helloworld!

可以看出第二处var被赋值为逗号分隔的字符串列表时,加与不加引号的变量输出差异(猜var={"hello", "world!"},参数为列表时相当于javascript中的message.apply(null, [argsArray])调用方式,也就是数组代替压栈传递参数,又或者像宏一样展开列表里的项作为参数;而加了引号则列表转为字符串ToString且固定为逗号分隔的字符串)。

注意:写路径时,如Windows上,需要双反斜杠:

#find_package(OpenSSL REQUIRED)
set(OPENSSL_INCLUDE_DIR "C:\\OpenSSL\\include")
set(OPENSSL_LIBRARIES "C:\\OpenSSL\\lib")

不然提示(不知为啥即使设置了OPENSSL_ROOT_DIR并从Win32 OpenSSL安装了x86 x64的,find_package就是找不到openssl库):

-- Looking for gethostbyname_r
-- Looking for gethostbyname_r - not found
CMake Error at CMakeLists.txt:678 (set):
  Syntax error in cmake code at

    I:/src/c/libevent/CMakeLists.txt:678

  when parsing string

    C:\OpenSSL\include

  Invalid character escape '\O'.


-- Configuring incomplete, errors occurred!
See also "I:/src/c/libevent/build/CMakeFiles/CMakeOutput.log".
See also "I:/src/c/libevent/build/CMakeFiles/CMakeError.log".

从命令行给脚本传递参数

# set(who "World!")
message(STATUS "Hello ${who}")

执行:cmake -P Hello.cmake -Dwho=World -P Hello.cmake

输出:

-- Hello
-- Hello world

注意,在-P指定的脚本中使用到 who 变量,那必须让-D在前,且-P脚本里变量创建和修改不会传播到另一个。

模块

调用其他模块,如调用find_package,会调用其他模块脚本FindJava.cmake,并返回一些值。 模块的参数和返回值等具体使用描述可参考FindJava.cmake里的解释。

find_package(Java COMPONENTS Development)
message("Result Java_JAVA_EXECUTABLE: ${Java_JAVA_EXECUTABLE}")
message("Result Java_VERSION: ${Java_VERSION}")
message("Result Java_VERSION_STRING: ${Java_VERSION_STRING}")
message("Result Java_INCLUDE_DIRS: ${Java_INCLUDE_DIRS}")

一般说来find_package一些库等可能使用到一些变量,指定编译器、指定

为Helloworld工程配置CMake脚本

这里根据爱好等,构建一个工程目录结构

+--Helloworld : a project root directory
 +--Build/ : build out of source
 +--Documentation/
 +--Include/ : common headers
 +--Source/
  +--Hello/ : a customized library
    --CMakeLists.txt
    --hello.c
    --Hello.h
  +--Demo/
    --CMakeLists.txt
    --main.cpp
    --main.h
 +--Test/
 +--Modules/
 `--CMakeLists.txt : a top cmake script file.

当然也可以把Hello放到Modules里,也许还可以把Modules改为Libs,Third等等,而Demo里的直接放到外面即Source里。

由于只演示一个简单Helloworld工程,如C:\Users\fangss\Desktop\Helloworld目录结构如下:

+--Helloworld     
 --CMakeLists.txt 
 --main.cpp

CMakeLists.txt,其中add_definitions追加一个预处理定义。

CMAKE_MINIMUM_REQUIRED(VERSION 2.6) # define minimum version
PROJECT(Helloworld) #The project name
ADD_EXECUTABLE(demo main.cpp)  #generate exe
add_definitions(-DDEMO_VERSION=${DEMO_VERSION}) # pass a preprocessor definition

main.cpp

#include <iostream>
using namespace std;

int main(int argc, char *argv[])
{
    #ifdef DEMO_VERSION
        cout << "demo version: " << DEMO_VERSION << endl;
    #endif
    cout<<"Hello World!"<<endl;
}

执行cd C:\Users\fangss\Desktop\Helloworld && "C:\Program Files\CMake\bin\cmake.exe" -D DEMO_VERSION=1.0 .,输出

-- Building for: Visual Studio 14 2015
-- The C compiler identification is MSVC 19.0.23026.0
-- The CXX compiler identification is MSVC 19.0.23026.0
-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/cl.exe
-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/cl.exe -
- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/cl.exe

-- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/cl.exe
 -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: C:/Users/fangss/Desktop

在Windows上自动探测MSVC并创建了Visual Studio解决方案。接下来,就可以用Visual Studio打开了。目录下文件变成这样:

2015/10/02  16:31    <DIR>          .
2015/10/02  16:31    <DIR>          ..
2015/10/02  16:31            52,923 ALL_BUILD.vcxproj
2015/10/02  16:31               289 ALL_BUILD.vcxproj.filters
2015/10/02  16:31            11,801 CMakeCache.txt
2015/10/02  16:31    <DIR>          CMakeFiles
2015/10/02  16:27               863 CMakeLists.txt
2015/10/02  16:31             1,309 cmake_install.cmake
2015/10/02  16:31            63,397 demo.vcxproj
2015/10/02  16:31               581 demo.vcxproj.filters
2015/10/02  16:31             3,134 Helloworld.sln
2015/10/02  16:28               214 main.cpp
2015/10/02  16:31            37,671 ZERO_CHECK.vcxproj
2015/10/02  16:31               526 ZERO_CHECK.vcxproj.filters

CMake命令行传递预处理定义处理 按照上面在CMakeLists.txt里使用add_definitions,就能够传递预处理定义了,搜一下,会发现在demo.vcxproj文件里:

grep --color -r "DEMO_VERSION" /cygdrive/c/Users/fangss/Desktop/HelloWorld

demo.vcxproj:      <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;DEMO_VERSION=1.0;CMAKE_INTDIR=\"RelWithDebInfo\";%(PreprocessorDefinitions)</PreprocessorDefinitions>

可以看出预处理定义为字符串(#define DEMO_VERSION "1.0")时,需要这样传递-D DEMO_VERSION=\"1.0\",否则"1.0"和1.0最终都是DEMO_VERSION=1.0

I:\src\c\libevent\build>timer cmake -DOPENSSL_ROOT_DIR="C:/Program Files (x86)/OpenSSL" -DOPENSSL_LIBRARIES="C:/Program Files (x86)/OpenSSL/lib" -DOPENSSL_INCLUDE_DIR="C:/Program Files (x86)/OpenSSL/include" -G "Visual Studio 14" ..

I:\src\c\libevent\build>timer cmake -DOPENSSL_ROOT_DIR="C:/Program Files (x86)/OpenSSL" -G "Visual Studio 14" .

timer cmake -DOPENSSL_ROOT_DIR="C:/Program Files (x86)/OpenSSL" -DOPENSSL_LIBRARIES="C:/Program Files (x86)/OpenSSL/lib" -DOPENSSL_INCLUDE_DIR="C:/Program Files (x86)/OpenSSL/include" -G "Visual Studio 14" ..
-- The C compiler identification is MSVC 19.0.23026.0
-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/cl.exe
-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/cl.exe -
- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Found Git: C:/cygwin/bin/git.exe
-- Looking for __GNU_LIBRARY__
-- Looking for __GNU_LIBRARY__ - not found
-- Looking for sys/types.h
-- Looking for sys/types.h - found
-- Looking for sys/socket.h
-- Looking for sys/socket.h - not found
-- Looking for netinet/in.h
-- Looking for netinet/in.h - not found
-- Looking for netinet/in6.h
-- Looking for netinet/in6.h - not found
-- Looking for unistd.h
-- Looking for unistd.h - not found
-- Looking for netdb.h
-- Looking for netdb.h - not found
-- Looking for dlfcn.h
-- Looking for dlfcn.h - not found
-- Looking for arpa/inet.h
-- Looking for arpa/inet.h - not found
-- Looking for fcntl.h
-- Looking for fcntl.h - found
-- Looking for inttypes.h
-- Looking for inttypes.h - found
-- Looking for memory.h
-- Looking for memory.h - found
-- Looking for poll.h
-- Looking for poll.h - not found
-- Looking for port.h
-- Looking for port.h - not found
-- Looking for signal.h
-- Looking for signal.h - found
-- Looking for stdarg.h
-- Looking for stdarg.h - found
-- Looking for stddef.h
-- Looking for stddef.h - found
-- Looking for stdint.h
-- Looking for stdint.h - found
-- Looking for stdlib.h
-- Looking for stdlib.h - found
-- Looking for strings.h
-- Looking for strings.h - not found
-- Looking for string.h
-- Looking for string.h - found
-- Looking for sys/devpoll.h
-- Looking for sys/devpoll.h - not found
-- Looking for sys/epoll.h
-- Looking for sys/epoll.h - not found
-- Looking for sys/eventfd.h
-- Looking for sys/eventfd.h - not found
-- Looking for sys/event.h
-- Looking for sys/event.h - not found
-- Looking for sys/ioctl.h
-- Looking for sys/ioctl.h - not found
-- Looking for sys/mman.h
-- Looking for sys/mman.h - not found
-- Looking for sys/param.h
-- Looking for sys/param.h - not found
-- Looking for sys/queue.h
-- Looking for sys/queue.h - not found
-- Looking for sys/select.h
-- Looking for sys/select.h - not found
-- Looking for sys/sendfile.h
-- Looking for sys/sendfile.h - not found
-- Looking for sys/stat.h
-- Looking for sys/stat.h - found
-- Looking for sys/time.h
-- Looking for sys/time.h - not found
-- Looking for sys/uio.h
-- Looking for sys/uio.h - not found
-- Looking for include files sys/types.h, ifaddrs.h
-- Looking for include files sys/types.h, ifaddrs.h - not found
-- Looking for mach/mach_time.h
-- Looking for mach/mach_time.h - not found
-- Looking for netinet/tcp.h
-- Looking for netinet/tcp.h - not found
-- Looking for sys/wait.h
-- Looking for sys/wait.h - not found
-- Looking for sys/resource.h
-- Looking for sys/resource.h - not found
-- Looking for sys/sysctl.h
-- Looking for sys/sysctl.h - not found
-- Looking for sys/timerfd.h
-- Looking for sys/timerfd.h - not found
-- Looking for errno.h
-- Looking for errno.h - found
-- Looking for epoll_create
-- Looking for epoll_create - not found
-- Looking for epoll_ctl
-- Looking for epoll_ctl - not found
-- Looking for eventfd
-- Looking for eventfd - not found
-- Looking for clock_gettime
-- Looking for clock_gettime - not found
-- Looking for fcntl
-- Looking for fcntl - not found
-- Looking for getaddrinfo
-- Looking for getaddrinfo - found
-- Looking for getnameinfo
-- Looking for getnameinfo - found
-- Looking for gettimeofday
-- Looking for gettimeofday - not found
-- Looking for getprotobynumber
-- Looking for getprotobynumber - found
-- Looking for getservbyname
-- Looking for getservbyname - found
-- Looking for inet_ntop
-- Looking for inet_ntop - found
-- Looking for inet_pton
-- Looking for inet_pton - found
-- Looking for kqueue
-- Looking for kqueue - not found
-- Looking for mmap
-- Looking for mmap - not found
-- Looking for pipe
-- Looking for pipe - not found
-- Looking for pipe2
-- Looking for pipe2 - not found
-- Looking for poll
-- Looking for poll - not found
-- Looking for port_create
-- Looking for port_create - not found
-- Looking for sendfile
-- Looking for sendfile - not found
-- Looking for sigaction
-- Looking for sigaction - not found
-- Looking for signal
-- Looking for signal - not found
-- Looking for splice
-- Looking for splice - not found
-- Looking for strlcpy
-- Looking for strlcpy - not found
-- Looking for strsep
-- Looking for strsep - not found
-- Looking for strtok_r
-- Looking for strtok_r - not found
-- Looking for strtoll
-- Looking for strtoll - found
-- Looking for vasprintf
-- Looking for vasprintf - not found
-- Looking for sysctl
-- Looking for sysctl - not found
-- Looking for accept4
-- Looking for accept4 - not found
-- Looking for arc4random
-- Looking for arc4random - not found
-- Looking for arc4random_buf
-- Looking for arc4random_buf - not found
-- Looking for epoll_create1
-- Looking for epoll_create1 - not found
-- Looking for getegid
-- Looking for getegid - not found
-- Looking for geteuid
-- Looking for geteuid - not found
-- Looking for getifaddrs
-- Looking for getifaddrs - not found
-- Looking for issetugid
-- Looking for issetugid - not found
-- Looking for mach_absolute_time
-- Looking for mach_absolute_time - not found
-- Looking for nanosleep
-- Looking for nanosleep - not found
-- Looking for usleep
-- Looking for usleep - not found
-- Looking for timeradd
-- Looking for timeradd - not found
-- Looking for timerclear
-- Looking for timerclear - not found
-- Looking for timercmp
-- Looking for timercmp - not found
-- Looking for timerfd_create
-- Looking for timerfd_create - not found
-- Looking for timerisset
-- Looking for timerisset - not found
-- Looking for putenv
-- Looking for putenv - found
-- Looking for setenv
-- Looking for setenv - not found
-- Looking for setrlimit
-- Looking for setrlimit - not found
-- Looking for umask
-- Looking for umask - not found
-- Looking for unsetenv
-- Looking for unsetenv - not found
-- Looking for gethostbyname_r
-- Looking for gethostbyname_r - not found
-- Looking for sys/types.h
-- Looking for sys/types.h - found
-- Looking for stdint.h
-- Looking for stdint.h - found
-- Looking for stddef.h
-- Looking for stddef.h - found
-- Check size of uint8_t
-- Check size of uint8_t - done
-- Check size of uint16_t
-- Check size of uint16_t - done
-- Check size of uint32_t
-- Check size of uint32_t - done
-- Check size of uint64_t
-- Check size of uint64_t - done
-- Check size of short
-- Check size of short - done
-- Check size of int
-- Check size of int - done
-- Check size of unsigned
-- Check size of unsigned - done
-- Check size of unsigned int
-- Check size of unsigned int - done
-- Check size of long
-- Check size of long - done
-- Check size of long long
-- Check size of long long - done
-- Performing Test HAVE_INLINE
-- Performing Test HAVE_INLINE - Success
-- Looking for TAILQ_FOREACH
-- Looking for TAILQ_FOREACH - not found
-- Looking for CTL_KERN
-- Looking for CTL_KERN - not found
-- Looking for KERN_ARND
-- Looking for KERN_ARND - not found
-- Looking for KERN_RANDOM
-- Looking for KERN_RANDOM - not found
-- Looking for RANDOM_UUID
-- Looking for RANDOM_UUID - not found
-- Looking for F_SETFD
-- Looking for F_SETFD - not found
-- Check size of fd_mask
-- Check size of fd_mask - failed
-- Check size of size_t
-- Check size of size_t - done
-- Check size of off_t
-- Check size of off_t - done
-- Check size of ssize_t
-- Check size of ssize_t - failed
-- Check size of SSIZE_T
-- Check size of SSIZE_T - done
-- Check size of socklen_t
-- Check size of socklen_t - done
-- Check size of pid_t
-- Check size of pid_t - failed
-- Check size of pthread_t
-- Check size of pthread_t - failed
-- Check size of uintptr_t
-- Check size of uintptr_t - done
-- Check size of void *
-- Check size of void * - done
-- Performing Test EVENT__HAVE_WAITPID_WITH_WNOWAIT
-- Performing Test EVENT__HAVE_WAITPID_WITH_WNOWAIT - Failed
-- Looking for _MINIX
-- Looking for _MINIX - not found
-- Looking for _POSIX_1_SOURCE
-- Looking for _POSIX_1_SOURCE - not found
-- Looking for _POSIX_SOURCE
-- Looking for _POSIX_SOURCE - not found
-- Check size of struct addrinfo
-- Check size of struct addrinfo - done
-- Check size of struct in6_addr
-- Check size of struct in6_addr - done
-- Performing Test EVENT__HAVE_STRUCT_IN6_ADDR_S6_ADDR16
-- Performing Test EVENT__HAVE_STRUCT_IN6_ADDR_S6_ADDR16 - Failed
-- Performing Test EVENT__HAVE_STRUCT_IN6_ADDR_S6_ADDR32
-- Performing Test EVENT__HAVE_STRUCT_IN6_ADDR_S6_ADDR32 - Failed
-- Check size of sa_family_t
-- Check size of sa_family_t - failed
-- Check size of struct sockaddr_in6
-- Check size of struct sockaddr_in6 - done
-- Performing Test EVENT__HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN
-- Performing Test EVENT__HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN - Failed
-- Performing Test EVENT__HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
-- Performing Test EVENT__HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - Failed
-- Check size of struct sockaddr_storage
-- Check size of struct sockaddr_storage - done
-- Performing Test EVENT__HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY
-- Performing Test EVENT__HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY - Success
-- Performing Test EVENT__HAVE_STRUCT_SOCKADDR_STORAGE___SS_FAMILY
-- Performing Test EVENT__HAVE_STRUCT_SOCKADDR_STORAGE___SS_FAMILY - Failed
CMake Error at C:/Program Files/CMake/share/cmake-3.6/Modules/FindPackageHandleStandardArgs.cmake:14
8 (message):
  Could NOT find OpenSSL, try to set the path to OpenSSL root folder in the
  system variable OPENSSL_ROOT_DIR (missing: OPENSSL_LIBRARIES) (found
  version "1.0.2h")
Call Stack (most recent call first):
  C:/Program Files/CMake/share/cmake-3.6/Modules/FindPackageHandleStandardArgs.cmake:388 (_FPHSA_FAI
LURE_MESSAGE)
  C:/Program Files/CMake/share/cmake-3.6/Modules/FindOpenSSL.cmake:370 (find_package_handle_standard
_args)
  CMakeLists.txt:677 (find_package)


-- Configuring incomplete, errors occurred!
See also "I:/src/c/libevent/build/CMakeFiles/CMakeOutput.log".
See also "I:/src/c/libevent/build/CMakeFiles/CMakeError.log".

I:\src\c\libevent\build>

Preparation

Tools

Envirenment Variables

  • JAVA_HOME=D:\ProgramFiles\Java\jdk1.8.0_40
  • MYSQL_TOOL=C:\Program Files (x86)\MySQL\MySQL Fabric 1.5.4 & MySQL Utilities 1.5.4 1.5
  • Path=C:\Perl64\site\bin;C:\Perl64\bin;D:\ProgramFiles\NASM;c:\cygwin\bin;C:\ProgramData\Oracle\Java\javapath;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0;C:\Program Files\TortoiseSVN\bin;C:\Program Files (x86)\Microsoft SQL Server\90\Tools\binn;C:\Program Files (x86)\Windows Kits\8.1\Windows Performance Toolkit;C:\Program Files\Microsoft SQL Server\110\Tools\Binn;"%MYSQL_TOOL%";"%MYSQL_TOOL%\Doctrine extensions for PHP";C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;%USERPROFILE%.dnx\bin;C:\Program Files\Microsoft DNX\Dnvm;C:\Program Files\Microsoft SQL Server\120\Tools\Binn;D:\ProgramFiles\GtkSharp\2.12\bin;C:\Program Files\nodejs;C:\Program Files\Process Lasso;D:\ProgramFiles\TortoiseGit\bin;C:\Program Files (x86)\Microsoft SQL Server\80\Tools\Binn;C:\Strawberry\c\bin;C:\Strawberry\perl\site\bin;C:\Strawberry\perl\bin

Note: If you use the special characters <, >, |, &, or ^, you must precede them with the escape character (^) or quotation marks. See more.

Build And Install

Run VS2015 开发人员命令提示(e.g. C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\Tools\VsDevCmd.bat)

See our preparation:

I:\src\c\openssl-1.1.0>where perl
C:\Perl64\bin\perl.exe
c:\cygwin\bin\perl.exe
C:\Strawberry\perl\bin\perl.exe

::PERL=C:\Strawberry\perl\bin\perl.exe

I:\src\c\openssl-1.1.0>where nmake
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\nmake.exe

:: VC-WIN32: PREFIX=%ProgramFiles(x86)%\OpenSSL, OPENSSLDIR=%CommonProgramFiles(x86)%\SSL
I:\src\c\openssl-1.1.0>echo %ProgramFiles(x86)%\OpenSSL
C:\Program Files (x86)\OpenSSL
I:\src\c\openssl-1.1.0>echo %CommonProgramFiles(x86)%\SSL
C:\Program Files (x86)\Common Files\SSL

PS: On Windows. To measure execution time:

:: Usage: timer command

:: timer.cmd: the variable name TIMER_START_HS is reserved.
:: hours:minutes:seconds.hundredths  mini-unit is hundredths of a second. Valid values are in the range 0 through 99.

@echo off
::setlocal enabledelayedexpansion 
:::: CMD /C "%*" avoids loss of TIMER_START_HS if there is an error indirectly executing a bad program by %*
::set TIMER_START_HS=%time%&&CMD /C "%*"&echo.&echo ==started: !TIMER_START_HS!, ended: %time%
:::: echo TIMER_START_HS = %TIMER_START_HS%, won't be modified by sub-CMD(Write-On-Copy).


::setlocal enabledelayedexpansion 
set TIMER_START_HS=%time%
CMD /C "%*"
echo.&echo ==started: %TIMER_START_HS%, ended: %time%

See more How to measure execution time of command in windows command line?.

:: C:\Program Files (x86)\Microsoft Visual Studio 14.0> 
cd /d I:\src\c\openssl-1.1.0

:: perl.exe Configure VC-WIN32 --prefix=OpenSSL_Installed_DirPath --openssldir=OpenSSL_Config_Cert_Key_DirPath
:: I:\src\c\openssl-1.1.0>
C:\Strawberry\perl\bin\perl.exe Configure VC-WIN32

:: Build OpenSSL
set START_TIME=%time% && nmake & echo ==started: %START_TIME%, ended: %time%

nmake install

Note: Run VS2015 开发人员命令提示 as Administrator and nmake install.

I:\src\c\openssl-1.1.0>nmake install
Cannot create directory C:/Program Files (x86)/OpenSSL: No such file or directory
NMAKE : fatal error U1077: “C:\Strawberry\perl\bin\perl.exe”: 返回代码“0x2”
Stop.

I:\src\c\openssl-1.1.0>mkdir "%ProgramFiles(x86)%\OpenSSL"
拒绝访问。

OpenSSL command line tool

Note:
echo will normally output a newline, which is suppressed with -n. Try this:echo -n foobar | sha256sum, see Generating a sha256 from the Linux command line

dgst - message digests:
  openssl dgst [-help] [-digest] [option...][file...]
  openssl [digest] [...]

enc - symmetric cipher routines:
  openssl enc -ciphername [-help] [-ciphers] [-in filename] [-out filename] [option...]
  • file... file or files to digest. If no files are specified then standard input is used.
  • -ciphers List all supported ciphers.
  • -in filename the input filename, standard input by default.
  • -out filename the output filename, standard output by default.
C:\Users\fangss>echo -n "chu" | openssl sha256 -hex
(stdin)= 7e52273c0b5976692270eeea52fbbfe4b7a3a5cdb6e0eeb623c97b1ab46e9149

C:\Users\fangss>openssl dgst -md5 -hex "C:\Program Files (x86)\OpenSSL\html\man1\dgst.html"
MD5(C:\Program Files (x86)\OpenSSL\html\man1\dgst.html)= 2d34d92a1a2651c2ed9bd5b978cace55


C:\Users\fangss>echo "chu" | openssl enc -base64
ImNodSIgDQo=

::encrypt

C:\Users\fangss>echo chu | openssl aes-256-cbc -e -a -pass pass:chu
U2FsdGVkX1/makJnDDNINOVufBdrr0itC9Ek46OTKDI=

C:\Users\fangss>echo chu | openssl aes-256-cbc -e -a -pass pass:chu
U2FsdGVkX1+iNJRROYnK3VQ3jFB8FkJNQ6QP/VMEplo=

C:\Users\fangss>echo chu | openssl aes-256-cbc -e -a -pass pass:chu -p
salt=C34FA33460F5BAAD
key=63ECE5B9CE0D8702EF21ABEC64ACE8B6661B2D13CAADDA66A0C7C5675D4A5E56
iv =9B9CD501CF8D794657B7B5E4C1CF61D6
U2FsdGVkX1/DT6M0YPW6rTQPsLQmJc5r/XesDZ+EJMg=

C:\Users\fangss>echo chu | openssl aes-256-cbc -a -pass pass:chu -p
salt=194D7B9D8FB808EF
key=B7C836BE724C0DCEA23A0C9212096A0D57D537F3A59E2697876F2A4454565798
iv =DD157A784B33628478D498FDEEDD6E12
U2FsdGVkX18ZTXudj7gI76do+q0rRD+X+0JYvtwxn4I=


:: decrypt

C:\Users\fangss>echo U2FsdGVkX19hWkmRmDwDxENVzy7crZfAESCgoCofJH4= | openssl enc -d -aes-256-cbc -a -k chu -p
chu

C:\Users\fangss>echo U2FsdGVkX18ZTXudj7gI76do+q0rRD+X+0JYvtwxn4I= | openssl enc -d -aes-256-cbc -a -k chu -p
salt=194D7B9D8FB808EF
key=B7C836BE724C0DCEA23A0C9212096A0D57D537F3A59E2697876F2A4454565798
iv =DD157A784B33628478D498FDEEDD6E12
chu

C:\Users\fangss>echo U2FsdGVkX18ZTXudj7gI76do+q0rRD+X+0JYvtwxn4I= | openssl enc -d -aes-256-cbc -a -p -k fss
salt=194D7B9D8FB808EF
key=086892155657BA7DBDA8FE94274B04D8E594224A72A09B30AE2067FF7CF28A4C
iv =4064D2D0F5565956B667BA816A2743B4
bad decrypt
4294956672:error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt:evp_enc.c:529:

Options:

  • -e encrypt the input data: this is the default. 加密

  • -d decrypt the input data. 解密

  • -a
    base64 process the data. This means that if encryption is taking place the data is base64 encoded after encryption. If decryption is set then the input data is base64 decoded before being decrypted. 加密后数据再base64编码或解密前数据先base64解码

  • -k password
    the password to derive the key from. This is for compatibility with previous versions of OpenSSL. Superseded by the -pass argument.

  • -pass pass:password
    See How to use password argument in via command line to openssl for decryption

  • -p print out the key and IV used. 打印使用的密钥和初始化向量(Initialization vector)。

Note: AES,cbc本质上和ecb差别不大,唯一区别是将前一次加密结果,与要加密的内容异或。因此,cbc的并行性较差,因为每次都要等待前一次的结果,而ecb则不用,速度较快。

方法EVP_BytesToKey - password based encryption routine根据(-k或-pass)输入的密码以及一些其他选项推导密钥和初始化向量。 没加盐则推导结果固定否则不固定,故AES加密结果也不一样

C:\Users\fangss>openssl enc -aes-256-cbc -a -P -k chu -nosalt
key=CBCEFAF71B4677CB8BCC006E0AEAA34AB6C2EEF639AC5C30BF006673D3455399
iv =FB25496334DA6684EA282996D192C54A

C:\Users\fangss>openssl enc -aes-256-cbc -a -P -k chu -nosalt
key=CBCEFAF71B4677CB8BCC006E0AEAA34AB6C2EEF639AC5C30BF006673D3455399
iv =FB25496334DA6684EA282996D192C54A

C:\Users\fangss>openssl enc -aes-256-cbc -a -P -k chu
salt=70A686804D5D305D
key=C960C2C0522BAD908F638DB48B915C3FB517332F7321BE78433745990B048EB3
iv =5B414C2D4D2B848E72181D34124F47D8

C:\Users\fangss>openssl enc -aes-256-cbc -a -P -k chu
salt=BE4E6B53F43D3B95
key=A92EA257B1961D3B3323D89B1C84CB911F7DA704334B69536D39D73D037E9EED
iv =19FFF39367F8459D6ACD4B28C18856B0

C:\Users\fangss>openssl enc -aes-256-cbc -a -P -k chu
salt=55364CFB6B0B5A02
key=9EE5168F7DBE9D701BE6237896237F9B9D3FC9FA96ECD6220A4BF39ADE5FC3CD
iv =EBA3FFB5BE8EBE0CFD5F6E7178658B83
@ssfang
Copy link
Author

ssfang commented Sep 10, 2016

分组密码加密中的四种模式:

  • CBC
    aes-cbc

图片来自:对称加密和分组加密中的四种模式(ECB、CBC、CFB、OFB)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment