Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OpenSSL: improve MinGW support on Windows #6079

Merged
merged 21 commits into from
Dec 31, 2024
Merged

OpenSSL: improve MinGW support on Windows #6079

merged 21 commits into from
Dec 31, 2024

Conversation

Doekin
Copy link
Contributor

@Doekin Doekin commented Dec 27, 2024

OpenSSL targeting MinGW can be built on Linux or MSYS2, but not directly on Windows. This PR introduces a workaround to enable building on Windows using Git Bash.

@Doekin Doekin marked this pull request as draft December 27, 2024 23:50
@Doekin

This comment was marked as outdated.

@Doekin Doekin marked this pull request as ready for review December 28, 2024 03:17
if jom then
package:add("deps", "jom", {private = true})
elseif is_subhost("windows") then
package:add("deps", "strawberry-perl", { private = true })
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why remove {system = false}, it will break some things. it will use incorrect perl in some systems and ci envs.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please share more details about the scenarios where the system Perl might fail? There might be a workaround we can implement to address this issue. Using the system Perl helps save disk space.

For your reference, I tested with Perl installed via scoop, and it seemed to work as expected.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't reproduce it because I don't remember what happened before. But since there is a clear comment to fix this problem by passing system = false, we shouldn't just remove it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment indicated that Perl bundled with GitForWindows fails to build OpenSSL. I encountered this issue too at the beginning. The error message is as follows:

Can't locate Pod/Usage.pm in @INC (you may need to install the Pod::Usage module) (@INC entries checked: . /usr/lib/perl5/site_perl /usr/share/perl5/site_perl /usr/lib/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib/perl5/core_perl /usr/share/perl5/core_perl) at configdata.pm line 11398.
BEGIN failed--compilation aborted at configdata.pm line 11398.
Compilation failed in require.
BEGIN failed--compilation aborted.

I looked into the config script and found that Pod::Usage is only used to generate help messages, which are shown with the ./Configure help command. I guess that the help message is not needed when installing the package. So, I removed the use of the Pod::Usage module, and it builds successfully using Perl from GitForWindows.

@@ -32,15 +32,18 @@ package("openssl")
if package:is_plat("android") and is_subhost("windows") and os.arch() == "x64" then
-- when building for android on windows, use msys2 perl instead of strawberry-perl to avoid configure issue
package:add("deps", "msys2", {configs = {msystem = "MINGW64", base_devel = true}, private = true})
elseif is_subhost("windows") and not package:is_precompiled() then
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and why not remove not package:is_precompiled()?
If you are using the build-artifacts binary, you do not need to compile openssl and install its build dependencies.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and here

Copy link
Contributor Author

@Doekin Doekin Dec 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, there is no is_precompiled now

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, there is no is_precompiled now

but we need is_precompiled.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I misunderstood.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you are downloading a precompiled binary, then all build dependencies do not need to be installed.

https://github.com/xmake-mirror/build-artifacts/releases?q=openssl&expanded=true

Copy link
Contributor Author

@Doekin Doekin Dec 30, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess the outer if not package:is_precompiled() then might work .

on_load(function (package)
if not package:is_precompiled() then

@Doekin
Copy link
Contributor Author

Doekin commented Dec 29, 2024

Supported Combinations of Targets and Windows Environments

  • Build for Windows in PowerShell with Strawberry Perl
  • Build for MinGW in Git Bash with bundled Perl

Unsupported Combinations of Targets and Environments

  • Build for MinGW in PowerShell
    • This is expected due to the reliance on many Unix-like shell commands in the makefile.

package:add("deps", "msys2", {configs = {msystem = "MINGW64", base_devel = true}, private = true})
elseif is_subhost("windows") then
import("lib.detect.find_tool")
local perl = find_tool("perl", {paths={"$(env PERL)"}})
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should not call find_tool in on_load

if on_check then
on_check(function (package)
import("lib.detect.find_tool")
local perl = assert(find_tool("perl", {paths={"$(env PERL)"}}), "package(openssl): perl not found!")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use package:find_tool and add spaces =

@@ -83,7 +102,13 @@ package("openssl")
table.insert(configs, "no-makedepend")
table.insert(configs, "/FS")
end
os.vrunv("perl", configs)
import("lib.detect.find_tool")
local perl = assert(find_tool("perl", {paths={"$(env PERL)"}}), "package(openssl): perl not found!")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should not call find_tool, we should use add_deps to bind perl path end and run perl

@Doekin Doekin marked this pull request as draft December 29, 2024 07:11
@Doekin Doekin marked this pull request as ready for review December 29, 2024 09:21
@SirLynix
Copy link
Member

I'm sorry but I don't understand what benefit this PR does, it seems complicated to just use the system perl instead of installing strawberry perl or am I missing something?

@Doekin
Copy link
Contributor Author

Doekin commented Dec 29, 2024

Thank you for your feedback. Let me clarify the reasoning behind this PR:

  1. When building OpenSSL for Windows, we can make use of a previously installed Strawberry Perl, as OpenSSL‘s configure script won't find the Perl bundled with Git Bash if we are in PowerShell or Command Prompt.
  2. For building OpenSSL for MinGW, Strawberry Perl cannot generate the Unix-style paths that OpenSSL requires, which leads to build failures. I added prompts to guide users to build in the appropriate environment. Suitable environments include Git Bash and MSYS2 shell.

Additionally, when building OpenSSL in Git Bash, we may encounter errors due to the missing POD::Usage Perl module, which is not included in the Perl bundled with Git Bash. However, this module is not essential for configuring OpenSSL's build; it is used to generate help information in the configure script. We can remove the use of POD::Usage to continue building.

I hope this clarifies the purpose of the changes.

@Doekin
Copy link
Contributor Author

Doekin commented Dec 31, 2024

Changes up to now

  • Allow Strawberry-Perl not installed by XMake to be used when targeting Windows.
  • Fix failure when running the configure script in Git Bash.
Example:

xrepo install -vD -p mingw openssl

Git Bash Configure Script

  • Avoid the creation of NUL file on Windows.
Example:

NUL File Issue
NUL File Issue

  • Fix The command line is too long error.
Example:

xmake install -vD -p mingw --toolchain=zig openssl

Command Line Too Long

  • Patch for using llvm-rc as the Windows resource compiler when targeting MinGW.

if package:is_plat("mingw") and package:has_tool("mrc", "llvm_rc", "llvm-rc", "rc") then
local cc = package:build_getenv("cc")
local cflags = opt.buildenvs.CFLAGS
local tmpfile = path.unix(os.tmpfile() .. ".c")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we need to remove tmpfile after running this script

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK

local cflags = opt.buildenvs.CFLAGS
local tmpfile = path.unix(os.tmpfile() .. ".c")
io.writefile(tmpfile, "int main(void) { return 0; }\n")
local compile_out, compile_err = try {function() return os.iorun(format("%s -v %s %s", cc, cflags, tmpfile)) end}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use lua table as argv and call os.iorunv(cc, argv)

Copy link
Contributor Author

@Doekin Doekin Dec 31, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I encountered an issue where the CFLAGS might be set to -m64 --target=x86_64-w64-windows-gnu, resulting in a concatenated command like clang "-v" "-m64 --target=x86_64-w64-windows-gnu" "a.c". This causes the following error:

clang-19: error: unknown argument: '-m64 --target=x86_64-w64-windows-gnu'
clang version 19.1.6 (https://github.com/llvm/llvm-project.git e21dc4bd5474d04b8e62d7331362edcc5648d7e5)
Target: x86_64-w64-windows-gnu
Thread model: posix
InstalledDir: D:/Applications/Scoop/apps/mingw-mstorsjo-llvm-ucrt/19.1.6-20241217/bin

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because buildenvs.CFLAGS has been merged to string. not lua table.

@@ -83,6 +100,7 @@ package("openssl")
table.insert(configs, "no-makedepend")
table.insert(configs, "/FS")
end
import("configure.patch")(package)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you test all openssl versions? does this patch work for all versions?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tested the latest version (1.1.1-w) with the following combinations of targets and environments:

  • Platform: Windows, Host: Windows
  • Platform: MinGW, Host: MSYS2 (Git Bash)
  • Platform: MinGW, Host: Linux
  • Platform: Linux, Host: Linux

The patch does not work for versions 1.0.0 and 1.0.2-u, resulting in the error:

error: @programdir\core\sandbox\modules\io.lua:188: cannot open file: Configurations/10-main.conf, Unknown Error (3)

Version 1.1.0-l failed with the error:

Unsupported options: no-tests

The patch works for versions 1.1.1-h and 1.1.1-p.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can use package:version():ge("1.1.1") to limit patch

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OpenSSL versions prior to 1.1.1 do not support the no-tests build flag, and there is a conflict between /FS and VC-WIN64A. After removing these flags, I still could not build OpenSSL 1.1.0-l for MinGW. While 1.1.0-l builds for Windows, 1.0.2-u does not.

Copy link
Member

@waruqi waruqi Dec 31, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can improve on_check to detect these cases (use version + is_plat).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I discovered that OpenSSL 1.0 requires a different installation method. Detailed explanations can be found here: How to Build OpenSSL 1.0 on Windows.

end

function main(package, opt)
-- _patch_for_llvm_rc(package, opt)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was an unintentional change.

@star-hengxing
Copy link
Contributor

This package does't have git urls, so you don't need to use package:gitref()

@waruqi waruqi merged commit c0a3807 into xmake-io:dev Dec 31, 2024
67 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants