Parse OpenSSL version from opensslv.h header file. Returns the version as a number matching OPENSSL_VERSION_NUMBER format: 0xMNN00PPSL where M=major, NN=minor, PP=patch, S=status(0xf=release,0x0=pre), L denotes as a long type literal
(o)
| 1429 | return '0.0' |
| 1430 | |
| 1431 | def get_openssl_version(o): |
| 1432 | """Parse OpenSSL version from opensslv.h header file. |
| 1433 | |
| 1434 | Returns the version as a number matching OPENSSL_VERSION_NUMBER format: |
| 1435 | 0xMNN00PPSL where M=major, NN=minor, PP=patch, S=status(0xf=release,0x0=pre), |
| 1436 | L denotes as a long type literal |
| 1437 | """ |
| 1438 | |
| 1439 | try: |
| 1440 | # Use the C compiler to extract preprocessor macros from opensslv.h |
| 1441 | args = ['-E', '-dM', '-include', 'openssl/opensslv.h', '-'] |
| 1442 | if not options.shared_openssl: |
| 1443 | args = ['-I', 'deps/openssl/openssl/include'] + args |
| 1444 | elif options.shared_openssl_includes: |
| 1445 | args = ['-I', options.shared_openssl_includes] + args |
| 1446 | else: |
| 1447 | for dir in o['include_dirs']: |
| 1448 | args = ['-I', dir] + args |
| 1449 | |
| 1450 | proc = subprocess.Popen( |
| 1451 | shlex.split(CC) + args, |
| 1452 | stdin=subprocess.PIPE, |
| 1453 | stdout=subprocess.PIPE, |
| 1454 | stderr=subprocess.PIPE |
| 1455 | ) |
| 1456 | with proc: |
| 1457 | proc.stdin.write(b'\n') |
| 1458 | out = to_utf8(proc.communicate()[0]) |
| 1459 | |
| 1460 | if proc.returncode != 0: |
| 1461 | warn('Failed to extract OpenSSL version from opensslv.h header') |
| 1462 | return 0 |
| 1463 | |
| 1464 | # Parse the macro definitions |
| 1465 | macros = {} |
| 1466 | for line in out.split('\n'): |
| 1467 | if line.startswith('#define OPENSSL_VERSION_'): |
| 1468 | parts = line.split() |
| 1469 | if len(parts) >= 3: |
| 1470 | macro_name = parts[1] |
| 1471 | macro_value = parts[2] |
| 1472 | macros[macro_name] = macro_value |
| 1473 | |
| 1474 | # Extract version components |
| 1475 | major = int(macros.get('OPENSSL_VERSION_MAJOR', '0')) |
| 1476 | minor = int(macros.get('OPENSSL_VERSION_MINOR', '0')) |
| 1477 | patch = int(macros.get('OPENSSL_VERSION_PATCH', '0')) |
| 1478 | |
| 1479 | # If major, minor and patch are all 0, this is probably OpenSSL < 3. |
| 1480 | if (major, minor, patch) == (0, 0, 0): |
| 1481 | version_number = macros.get('OPENSSL_VERSION_NUMBER') |
| 1482 | # Prior to OpenSSL 3 the value should be in the format 0xMNN00PPSL. |
| 1483 | # If it is, we need to strip the `L` suffix prior to parsing. |
| 1484 | if version_number[:2] == "0x" and version_number[-1] == "L": |
| 1485 | return int(version_number[:-1], 16) |
| 1486 | |
| 1487 | # Check if it's a pre-release (has non-empty PRE_RELEASE string) |
| 1488 | pre_release = macros.get('OPENSSL_VERSION_PRE_RELEASE', '""').strip('"') |