Opened 7 months ago

Closed 4 months ago

#18640 closed enhancement (fixed)

Detect building the samples with nmake without specifying CPU=x64

Reported by: NewPagodi Owned by:
Priority: normal Milestone:
Component: build Version: dev-latest
Keywords: nmake Cc: m0081@…
Blocked By: Blocking:
Patch: no

Description

After the recent changes for dpi awareness, the library and samples will build with nmake, but the resulting executables can not be run.

I'm using visual studio 2017 community edition and the command used to build both the library and minimal sample is nmake -f makefile.vc BUILD=debug SHARED=1. The command is executed in the "x64 native tools command prompt for VS 2017" shell.

After building the library and minimal sample, when you try to run the sample you receive the error message

The application has failed to start because its side-by-side configuration is incorrect. Please see the application event log or use the command-line sxstrace.exe tool for more detail.

I extracted the manifest with mt.exe and (after pretty printing) it looks like this:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" manifestVersion="1.0">
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="x86" publicKeyToken="6595b64144ccf1df" language="*"/>
    </dependentAssembly>
  </dependency>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="amd64" publicKeyToken="6595b64144ccf1df" language="*"/>
    </dependentAssembly>
  </dependency>
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel level="asInvoker" uiAccess="false"/>
      </requestedPrivileges>
    </security>
  </trustInfo>
  <asmv3:application>
    <asmv3:windowsSettings>
      <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
      <dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2, system</dpiAwareness>
    </asmv3:windowsSettings>
  </asmv3:application>
  <ms_compatibility:compatibility xmlns:ms_compatibility="urn:schemas-microsoft-com:compatibility.v1" xmlns="urn:schemas-microsoft-com:compatibility.v1">
    <ms_compatibility:application xmlns:ms_compatibility="urn:schemas-microsoft-com:compatibility.v1">
      <ms_compatibility:supportedOS xmlns:ms_compatibility="urn:schemas-microsoft-com:compatibility.v1" Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
      <ms_compatibility:supportedOS xmlns:ms_compatibility="urn:schemas-microsoft-com:compatibility.v1" Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
      <ms_compatibility:supportedOS xmlns:ms_compatibility="urn:schemas-microsoft-com:compatibility.v1" Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
      <ms_compatibility:supportedOS xmlns:ms_compatibility="urn:schemas-microsoft-com:compatibility.v1" Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
      <ms_compatibility:supportedOS xmlns:ms_compatibility="urn:schemas-microsoft-com:compatibility.v1" Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
    </ms_compatibility:application>
  </ms_compatibility:compatibility>
</assembly>

The problem seems to be that it's listing both the x86 and amd64 common controls as dependencies.

However, that doesn't seem to be the whole problem. I tried building and linking the minimal sample by hand without the embeded manifest. But then I get the error message

The application was unable to start correctly (0xc0150002). Click OK to close the application.

Google says this error is usually due to a missing vc redistributable package, but that can't be the case here because when built using the visual studio sln file, everything works. It's only when using nmake that these problems appear.

git bisect shows that the problematic commit is bed8cd7b52acf2290a8dccd3119a982aa14ebdad.

Change History (9)

comment:1 Changed 7 months ago by MaartenB

For x64 builds, you also have to specify CPU=X64, see https://github.com/wxWidgets/wxWidgets/blob/master/build/msw/config.vc#L49

It used to work without, but after the DPI additions it is required.

comment:2 follow-up: Changed 7 months ago by vadz

  • Status changed from new to confirmed
  • Summary changed from The samples will not run when built with nmake to The samples will not run when built with nmake without CPU=x64

I wonder if we could default TARGET_CPU to the value of VSCMD_ARG_TGT_ARCH which is defined as x64 for at least MSVS 2017 and 2019. Unfortunately there doesn't seem to be anything that we could do for the earlier versions.

Even just detecting that we're using non-x86 compiler and giving an error if CPU is not defined would be better than the current behaviour too, but the problem is that I don't really know how to detect this. Does anybody?

comment:3 in reply to: ↑ 2 Changed 7 months ago by NewPagodi

Sorry for the noise. Somehow, I've never noticed that CPU was supposed to be defined when using nmake.

Replying to vadz:

Even just detecting that we're using non-x86 compiler and giving an error if CPU is not defined would be better than the current behaviour too, but the problem is that I don't really know how to detect this. Does anybody?

I looked over the changes that were made common.bkl to accommodate the hidpi manifests. Analogous to the new WIN32_DPI_LINKFLAG, maybe a new variable could be be added named something like TARGET_CPU_COMPFLAG that is set as follows:

    <set var="TARGET_CPU_COMPFLAG"></set>
    <if cond="FORMAT=='msvc'">
        <set var="TARGET_CPU_COMPFLAG">
            <if cond="TARGET_CPU==''">TARGET_CPU_COMPFLAG=0</if>
        </set>
    </if>

Then added to the settings with

    <template id="common_settings">
        ...
        <if cond="FORMAT=='msvc'">
            <define>$(TARGET_CPU_COMPFLAG)</define>
        </if>
        ...
    </template>

If I'm understanding things right, that should create a compiler define that will only be used the nmake .vc file and will be defined and set to 0 if CPU isn't passed on the command line.

Then somewhere in the wxWidgets files, add a check like this

#ifdef _MSC_VER
    #if defined(WXBUILDING) && defined(_WIN64) && defined(TARGET_CPU_COMPFLAG) && (TARGET_CPU_COMPFLAG == 0)
        #error CPU must be defined
    #endif
#endif

Does that seem like a plan that could work? It's entirely possible I'm misunderstanding how the bkl files work and this is completely wrong.

comment:4 Changed 7 months ago by vadz

  • Summary changed from The samples will not run when built with nmake without CPU=x64 to Detect building the samples with nmake without specifying CPU=x64
  • Type changed from build error to enhancement

Thanks, I think this could work except we shouldn't checking for WXBUILDING because we want to detect this when compiling applications using the library (e.g. the samples) and not the library itself. We should also test for !defined(WX_CPU_X86) for completeness and not just for Win64, but it's a detail.

comment:5 Changed 7 months ago by NewPagodi

  • Cc m0081@… added

Actually don't we want to detect this when building the library? I just tried building the library again without setting CPU and dumped the manifest for wxmsw314ud_core_vc_custom.dll and that manifest is listing dependencies for both the x86 and amd64 version of common controls just like the manifest for minimal.exe I listed in the first post.

I'm pretty sure this is the cause of the second error I mentioned in the first post (the error windows gives is completely unhelpful, so I can't say for sure). But I think any application that tries to use the dlls built when CPU isn't defined will fail to start.

I was thinking that erroring out when building the libraries is better than producing unusable libs and dlls.

comment:6 Changed 7 months ago by vadz

Sorry for being unclear: I agree that we should detect this when building the library (although it's probably harmless in the static lib case, so maybe only when building it as DLL), but I also think we should detect it when building the applications. I.e. I'd remove WXBUILDING test entirely, not replace it with WXUSINGDLL or something like this.

comment:7 Changed 4 months ago by Maarten Bent <MaartenBent@…>

In 284b25ce0/git-wxWidgets:

Automatically detect if target architecture is x64 in .vc file

This allows a successful build even if the user omits specifying CPU=X64.

See #18640

comment:8 Changed 4 months ago by Maarten Bent <MaartenBent@…>

In f1a017539/git-wxWidgets:

Generate an error when the CPU parameter is not specified and cannot be determined

See #18640

comment:9 Changed 4 months ago by vadz

  • Resolution set to fixed
  • Status changed from confirmed to closed

I think Maarten's changes resolve all the issues here (thanks again!), so it can be closed -- but please reopen if I'm missing/forgetting something. TIA!

Note: See TracTickets for help on using tickets.