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

[bug] libiconv.res.obj : fatal error LNK1112: module machine type 'x64' conflicts with target machine type 'x86' #20689

Closed
cyberflashguru opened this issue Oct 18, 2023 · 6 comments · Fixed by #20693
Assignees

Comments

@cyberflashguru
Copy link
Contributor

Environment details

  • Operating System+version: Microsoft Windows 11 Pro, 10.0.22621 N/A Build 22621
  • Compiler+version: Visual Studio 2022 C++17
  • Conan version: 1.60.2
  • Python version: 3.10.11

Steps to reproduce

This bug was initially reported here: https://lists.defectivebydesign.org/archive/html/bug-gnu-libiconv/2021-01/msg00002.html
and I'm currently running into the same error.

Below are the libiconv build steps, the fatal error and a suggested patch.

Creating the libiconv library

  1. Clone the repository:

git clone https://github.com/conan-io/conan-center-index.git

  1. Navigate to the directory:

cd conan-center-index/recipes/libiconv/all

Build of x86 libiconv/1.17

  1. Remove any existing libiconv/1.17 conan package:

conan remove libiconv/1.17

  1. Export this recipe to your local Conan cache:

conan export c:\Projects\conan-center-index\recipes\libiconv\all libiconv/1.17@/

  1. Build an x86 libiconv/1.17 version and notice the fatal error:

...
libtool: compile: windres -DPACKAGE_VERSION_STRING=\"1.17\" -DPACKAGE_VERSION_MAJOR=1 -DPACKAGE_VERSION_MINOR=17 -DPACKAGE_VERSION_SUBMINOR=0 -i /c/users/johnsmith/.conan/data/libiconv/1.17///build/e7f407375b48ca2f89135f6704b636cb32edd0ff/src/lib/../windows/libiconv.rc --output-format=coff -o libiconv.res.obj
/bin/sh ../libtool --mode=link /c/users/johnsmith/.conan/data/libiconv/1.17///build/e7f407375b48ca2f89135f6704b636cb32edd0ff/src/build-aux/compile cl -nologo -debug -MT -Zi -O2 -Ob1 -FS -o libiconv.la -rpath /lib -version-info 8:1:6 -no-undefined iconv.lo localcharset.lo relocatable.lo libiconv.res.lo
libtool: link: /c/users/johnsmith/.conan/data/libiconv/1.17///build/e7f407375b48ca2f89135f6704b636cb32edd0ff/src/build-aux/ar-lib lib cr .libs/iconv.lib iconv.obj localcharset.obj relocatable.obj libiconv.res.obj
libiconv.res.obj : fatal error LNK1112: module machine type 'x64' conflicts with target machine type 'x86'
make[1]: *** [Makefile:77: libiconv.la] Error 88
make[1]: Leaving directory '/c/Users/johnsmith/.conan/data/libiconv/1.17///build/e7f407375b48ca2f89135f6704b636cb32edd0ff/build-relwithdebinfo/lib'
make: *** [Makefile:33: all] Error 2
libiconv/1.17:
libiconv/1.17: ERROR: Package 'e7f407375b48ca2f89135f6704b636cb32edd0ff' build failed
libiconv/1.17: WARN: Build folder C:\Users\johnsmith.conan\data\libiconv\1.17__\build\e7f407375b48ca2f89135f6704b636cb32edd0ff\build-relwithdebinfo
ERROR: libiconv/1.17: Error in build() method, line 126
autotools.make()
ConanException: Error 2 while executing make -j16
Executing error: Program conan: returned error code: 1
...

I tried 3 ways to resolve this error:

  1. Created a patch file called C:\Projects\conan-center-index\recipes\libiconv\all\patches\windres-options.patch

--- src/windows/windres-options
+++ src/windows/windres-options
@@ -34 +33,0 @@ q

  • echo "--target=pe-i386 "

and updated conandata.yml as follows:

patches:
"1.16":
- patch_file: "patches/0001-libcharset-fix-linkage.patch"
"1.17":
- patch_file: "patches/ windres-options.patch"

but, ran into this error

C:\Users\johnsmith.conan\data\libiconv\1.17__\build\e7f407375b48ca2f89135f6704b636cb32edd0ff\patches/windres-options.patch: source/target file does not exist:
[Config:x86] --- b'src/windows/windres-options'
[Config:x86] +++ b'src/windows/windres-options'

  1. Using the patch.exe, I ran this command from the conanfile.py and got an access violation:

self.run(r'"C:\Program Files\Git\usr\bin\patch.exe" -p0 -R --binary < {}'.format(patch_file_path), cwd=parent_build_folder, output=True)

so no luck with this method.

  1. The following method did work! It patches "windres-options" directly with the option --target=pe-i386

Creating the libiconv resource Patch

Navigate to the directory:

cd conan-center-index/recipes/libiconv/all

conanfile.py Modifications:

Added a new function called apply_resource_patch()

def apply_resource_patch(self):
    if self.settings.arch == "x86":
        windres_options_path = os.path.join(self.source_folder, "windows", "windres-options")
        self.output.info("Applying {} resource patch: {}".format(self.settings.arch, windres_options_path))
        with open(windres_options_path, 'r') as file:
            lines = file.readlines()
        lines.insert(8, 'echo "--target=pe-i386"\n')
        with open(windres_options_path, 'w') as file:
            file.writelines(lines)

def build(self): 
    apply_conandata_patches(self)
    self.apply_resource_patch()
    autotools = Autotools(self)
    autotools.configure()
    autotools.make()

which correctly added this option --target=pe-i386 to the windres commandline during the build:

libtool: compile: windres --target=pe-i386 -DPACKAGE_VERSION_STRING=\"1.17\" -DPACKAGE_VERSION_MAJOR=1 -DPACKAGE_VERSION_MINOR=17 -DPACKAGE_VERSION_SUBMINOR=0 -i /c/users/johnsmith/.conan/data/libiconv/1.17///build/e7f407375b48ca2f89135f6704b636cb32edd0ff/src/lib/../windows/libiconv.rc --output-format=coff -o libiconv.res.obj

Everything now builds successfully and that patch resolves the x86 build error:

libiconv.res.obj : fatal error LNK1112: module machine type 'x64' conflicts with target machine type 'x86'

I'd like to be able to use the standard apply_conandata_patches() method for libiconv instead of modifying the file directly via the custom patch function apply_resource_patch().

There are 3 proposed patch methods above:

  1. Use the standard approach apply_conandata_patches()
  2. Use patch.exe to apply the patch
  3. Use python code to call apply_conandata_patches()

Hopefully a patch can be added to resolve the x86 only fatal error.

Thanks!

Logs

No response

@memsharded
Copy link
Member

Hi @cyberflashguru

Thanks for your report. I can reproduce it, by moving to the libiconv folder and doing a single:

$ conan create . --version=1.17 -s arch=x86

I can see the error (it is not necessary to do the export + remove + etc)

Thanks very much also for your detailed investigation.
I think the limitation here is that the apply_conandata_patches() is intended for patches that apply to all binary configurations, while this one is very specific for this x86 configuration. I don't know enough how the windres-options file works. Looking in the internet I have only found https://fossies.org/linux/libiconv/INSTALL.windows, which looks outdated, any link or reference to the --target=pe-i386 fix? Isn't it possible to pass it in any other way that is not patching the windres-options file?

@cyberflashguru
Copy link
Contributor Author

Good point about apply_conandata_patches() being specific to ALL binary configs:

I think the limitation here is that the apply_conandata_patches() is intended for patches that apply to all binary configurations, while this one is very specific for this x86 configuration.

In the build folder \src\lib\Makefile.in, that file calls this libtool passing /windows/windres-options which is responsible for adding options to windres.exe. By patching the windres-options file for an x86 build, it works nicely.

libiconv.res.lo : $(srcdir)/../windows/libiconv.rc
	$(LIBTOOL_COMPILE) --tag=RC $(RC) `$(SHELL) $(srcdir)/../windows/windres-options --escape $(PACKAGE_VERSION)` -i $(srcdir)/../windows/libiconv.rc -o libiconv.res.lo --output-format=coff

On Windows, typing this command windres -h will output this target usage:

windres: supported targets: pe-x86-64 pei-x86-64 pe-bigobj-x86-64 elf64-x86-64 elf64-l1om elf64-k1om pe-i386 pei-i386 elf32-i386 elf32-iamcu elf64-little elf64-big elf32-little elf32-big plugin srec symbolsrec verilog tekhex binary ihex

Also, I recall this SO question and it suggested using RCFLAGS, but I had no luck with that approach.

For now, I've patched it directly using this specific x86 python code

def apply_resource_patch(self):
    if self.settings.arch == "x86":
        windres_options_path = os.path.join(self.source_folder, "windows", "windres-options")
        self.output.info("Applying {} resource patch: {}".format(self.settings.arch, windres_options_path))
        with open(windres_options_path, 'r') as file:
            lines = file.readlines()
        lines.insert(8, 'echo "--target=pe-i386"\n')
        with open(windres_options_path, 'w') as file:
            file.writelines(lines)

def build(self): 
    apply_conandata_patches(self)
    self.apply_resource_patch()
    autotools = Autotools(self)
    autotools.configure()
    autotools.make()

which has the effect of adding the target option --target=pe-i386 as follows

windres-options

#!/bin/sh
# Usage: windres-options [--escape] PACKAGE_VERSION
# Outputs a set of command-line options for 'windres', containing definitions
# for the preprocessor variables
#   PACKAGE_VERSION_STRING
#   PACKAGE_VERSION_MAJOR
#   PACKAGE_VERSION_MINOR
#   PACKAGE_VERSION_SUBMINOR
echo "--target=pe-i386"

Thanks for your time.

@memsharded
Copy link
Member

Ok, thanks very much for the explanations.
I think it would be worth to submit this PR to conan-center-index to fix this for other potential Conan users that would hit this.

I'd recommend trying to simplify it to a one liner replace_in_file():

def _apply_resource_patch(self):  #Note the _ to make it private, just in case
    if self.settings.arch == "x86":
        windres_options_path = os.path.join(self.source_folder, "windows", "windres-options")
        self.output.info("Applying {} resource patch: {}".format(self.settings.arch, windres_options_path))
        replace_in_file(self, windres_options_path,  '#   PACKAGE_VERSION_SUBMINOR',  '\necho "--target=pe-i386"\n')

With PACKAGE_VERSION_SUBMINOR string just pick the substring that applies.

@cyberflashguru
Copy link
Contributor Author

I'll submit a PR to conan-center-index. Thanks.

conan-center-index\recipes\libiconv\all\conanfile.py

Add replace_in_file to the imports:

from conan.tools.files import (
    apply_conandata_patches,
    copy,
    export_conandata_patches,
    get,
    rename,
    rm,
    rmdir,
    replace_in_file
)

Add echo "--target=pe-i386" to resolve the resource error:

    def _apply_resource_patch(self):
        if self.settings.arch == "x86":
            windres_options_path = os.path.join(self.source_folder, "windows", "windres-options")
            self.output.info("Applying {} resource patch: {}".format(self.settings.arch, windres_options_path))
            replace_in_file(self, windres_options_path, '#   PACKAGE_VERSION_SUBMINOR', '#   PACKAGE_VERSION_SUBMINOR\necho "--target=pe-i386"', strict=True)

    def build(self): 
        apply_conandata_patches(self)
        self._apply_resource_patch()
        autotools = Autotools(self)
        autotools.configure()
        autotools.make()

@memsharded
Copy link
Member

Ok, I'll move this ticket to conan-center-index then.

@memsharded memsharded transferred this issue from conan-io/conan Oct 19, 2023
@memsharded
Copy link
Member

When you do a PR, you can add in the comment a Close https://github.com/conan-io/conan-center-index/issues/20689 to automatically close this ticket when your PR gets merged. Thanks again for the feedback and contribution!

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

Successfully merging a pull request may close this issue.

2 participants