1 /+ dub.sdl: 2 name "script" 3 +/ 4 5 /** 6 * This program will attempt to detect which version of openssl is installed 7 * 8 * End-users might have different versions of OpenSSL installed. 9 * The version might ever differ among members of a development team. 10 * 11 * This script attempts to first calls `pkg-config` to find out the version, 12 * then reverts to calling the `openssl` binary if `pkg-config` didn't work. 13 * 14 * It is called directly as a `preGenerateCommand` (see dub.sdl). 15 * To use it with another build system, pass the directory in which to write 16 * the `version_.di` file as first and only argument. The directory 17 * must exist, this script will not create it. 18 */ 19 module generate_version; 20 21 import std.algorithm; 22 import std.conv; 23 import std.file; 24 import std.functional; 25 import std.path; 26 import std.process; 27 import std.range; 28 import std.stdio; 29 import std.string; 30 import std.uni; 31 32 // file full path is: $SOME_PATH/openssl/scripts/generate_version.d 33 // We want: $SOME_PATH/openssl/deimos/openssl/ 34 immutable TARGET_DIR_PATH = __FILE_FULL_PATH__ 35 .dirName.dirName.buildPath("source", "deimos", "openssl"); 36 37 void main(string[] args) 38 { 39 string target; 40 41 if (args.length == 2) 42 { 43 assert(args[1].isDir(), 44 "OpenSSL version detection: Argument '" ~ args[1] ~ "' is not a directory"); 45 target = args[1].buildPath("version_.di"); 46 } 47 else 48 { 49 assert(args.length == 1, 50 "OpenSSL version detection expects only one argument, " ~ 51 "a directory path where to write `version_.di`"); 52 target = TARGET_DIR_PATH.buildPath("version_.di"); 53 } 54 55 string opensslVersion; 56 try 57 { 58 const res = execute(["pkg-config", "openssl", "--modversion"]); 59 if (res.status == 0) 60 opensslVersion = res.output.strip(); 61 } 62 catch (Exception e) {} 63 64 if (!opensslVersion.length) try 65 { 66 const res = execute(["openssl", "version"]).output; 67 if (res.canFind("OpenSSL ")) 68 { 69 opensslVersion = res.splitter(" ").dropOne.front.filter!(not!(std.uni.isAlpha)).text; 70 } 71 else if (res.canFind("LibreSSL ")) 72 { 73 writeln("\tWarning: Your default openssl binary points to LibreSSL, which is not supported."); 74 version (OSX) 75 { 76 writeln("\tOn Mac OSX, this is the default behavior."); 77 writeln("\tIf you installed openssl via a package manager, you need to tell DUB how to find it."); 78 writeln("\tAssuming brew, run [brew link openssl] and follow the instructions for pkg-config.\n"); 79 } 80 } 81 } 82 catch (Exception e) {} 83 84 if (!opensslVersion.length) 85 { 86 writeln("\tWarning: Could not find OpenSSL version via pkg-config nor by calling the openssl binary."); 87 writeln("\tAssuming version 1.1.0."); 88 writeln("\tYou might need to export PKG_CONFIG_PATH or install the openssl package if you have a library-only package."); 89 opensslVersion = "1.1.0h"; 90 } 91 auto data = format(q{/** 92 * Provide the version of the libssl being linked to at compile time 93 * 94 * This module was auto-generated by deimos/openssl's script/generate_version.d 95 * Manual edit might get overwritten by later build. 96 * 97 * This module should not be directly dependend upon. 98 * Instead, use `deimos.openssl.opensslv`, which handles explicit overrides 99 * provides a uniform interface, and a few utilities. 100 */ 101 module deimos.openssl.version_; 102 103 /// Ditto 104 package enum OpenSSLTextVersion = "%s"; 105 }, opensslVersion); 106 107 // Only write the file iff it has changed or didn't exist before. 108 // This way timestamp-based build system will not rebuild, 109 // and changes on the installed OpenSSL will be correctly detected. 110 if (!target.exists || target.readText.strip != data.strip) 111 data.toFile(target); 112 }