From ef7cb9f280175d026b16e8e02ecda9ec87d7fd6d Mon Sep 17 00:00:00 2001 From: Andrei Alexeyev <0x416b617269@gmail.com> Date: Thu, 21 Dec 2017 22:36:30 +0200 Subject: [PATCH 1/4] [windows] make compile_resources use custom targets instead of generators --- mesonbuild/modules/windows.py | 15 ++-- .../inc/meson.build | 1 + .../inc/resource/resource.h | 1 + .../meson.build | 69 ++++++++++++++++++ .../13 resources with custom targets/prog.c | 14 ++++ .../res/gen-res.py | 6 ++ .../res/meson.build | 13 ++++ .../res/myres.rc.in | 4 + .../res/sample.ico | Bin 0 -> 9662 bytes 9 files changed, 118 insertions(+), 5 deletions(-) create mode 100644 test cases/windows/13 resources with custom targets/inc/meson.build create mode 100644 test cases/windows/13 resources with custom targets/inc/resource/resource.h create mode 100644 test cases/windows/13 resources with custom targets/meson.build create mode 100644 test cases/windows/13 resources with custom targets/prog.c create mode 100755 test cases/windows/13 resources with custom targets/res/gen-res.py create mode 100644 test cases/windows/13 resources with custom targets/res/meson.build create mode 100644 test cases/windows/13 resources with custom targets/res/myres.rc.in create mode 100644 test cases/windows/13 resources with custom targets/res/sample.ico diff --git a/mesonbuild/modules/windows.py b/mesonbuild/modules/windows.py index c16d7a840..22bf49b2a 100644 --- a/mesonbuild/modules/windows.py +++ b/mesonbuild/modules/windows.py @@ -67,11 +67,16 @@ class WindowsModule(ExtensionModule): suffix = 'o' if not rescomp.found(): raise MesonException('Could not find Windows resource compiler %s.' % ' '.join(rescomp.get_command())) - res_kwargs = {'output': '@BASENAME@.' + suffix, - 'arguments': res_args} - res_gen = build.Generator([rescomp], res_kwargs) - res_output = res_gen.process_files('Windows resource', args, state) - return ModuleReturnValue(res_output, [res_output]) + + res_kwargs = { + 'output': '@BASENAME@.' + suffix, + 'input': args, + 'command': [rescomp] + res_args, + } + + res_target = build.CustomTarget('Windows resource', state.subdir, state.subproject, res_kwargs) + + return ModuleReturnValue(res_target, [res_target]) def initialize(): return WindowsModule() diff --git a/test cases/windows/13 resources with custom targets/inc/meson.build b/test cases/windows/13 resources with custom targets/inc/meson.build new file mode 100644 index 000000000..b8b511a98 --- /dev/null +++ b/test cases/windows/13 resources with custom targets/inc/meson.build @@ -0,0 +1 @@ +inc = include_directories('resource') diff --git a/test cases/windows/13 resources with custom targets/inc/resource/resource.h b/test cases/windows/13 resources with custom targets/inc/resource/resource.h new file mode 100644 index 000000000..dbdd5094d --- /dev/null +++ b/test cases/windows/13 resources with custom targets/inc/resource/resource.h @@ -0,0 +1 @@ +#define ICON_ID 1 diff --git a/test cases/windows/13 resources with custom targets/meson.build b/test cases/windows/13 resources with custom targets/meson.build new file mode 100644 index 000000000..ddb7d6e8a --- /dev/null +++ b/test cases/windows/13 resources with custom targets/meson.build @@ -0,0 +1,69 @@ +project('winmain', 'c') + +# MinGW windres has a bug due to which it doesn't parse args with space properly: +# https://github.com/mesonbuild/meson/pull/1346 +# https://sourceware.org/bugzilla/show_bug.cgi?id=4933 +if meson.get_compiler('c').get_id() == 'gcc' and host_machine.system() == 'windows' + # Construct build_to_src and skip this test if it has spaces + # because then the -I flag to windres will also have spaces + # and we know the test will fail + src_parts = meson.source_root().split('/') + build_parts = meson.build_root().split('/') + + # Get the common path (which might just be '/' or 'C:/') + common = [] + done = false + count = 0 + if src_parts.length() > build_parts.length() + parts = build_parts + other = src_parts + else + parts = src_parts + other = build_parts + endif + foreach part : parts + if not done and part == other.get(count) + common += [part] + else + done = true + endif + count += 1 + endforeach + + # Create path components to go down from the build root to the common path + count = 0 + rel = build_parts + foreach build : build_parts + if count < build_parts.length() - common.length() + rel += ['..'] + endif + count += 1 + endforeach + + # Create path components to go up from the common path to the build root + count = 0 + foreach src : src_parts + if count >= common.length() + rel += [src] + endif + count += 1 + endforeach + + build_to_src = '/'.join(rel) + + if build_to_src.contains(' ') + message('build_to_src is: ' + build_to_src) + error('MESON_SKIP_TEST build_to_src has spaces') + endif + # Welcome to the end of this conditional. + # We hope you never have to implement something like this. +endif + +subdir('inc') +subdir('res') + +exe = executable('prog', 'prog.c', + res, + gui_app : true) + +test('winmain', exe) diff --git a/test cases/windows/13 resources with custom targets/prog.c b/test cases/windows/13 resources with custom targets/prog.c new file mode 100644 index 000000000..2c6f1535d --- /dev/null +++ b/test cases/windows/13 resources with custom targets/prog.c @@ -0,0 +1,14 @@ +#include + +#define MY_ICON 1 + +int APIENTRY +WinMain( + HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpszCmdLine, + int nCmdShow) { + HICON hIcon; + hIcon = LoadIcon(NULL, IDI_APPLICATION); + return hIcon ? 0 : 1; +} diff --git a/test cases/windows/13 resources with custom targets/res/gen-res.py b/test cases/windows/13 resources with custom targets/res/gen-res.py new file mode 100755 index 000000000..2feb02f5b --- /dev/null +++ b/test cases/windows/13 resources with custom targets/res/gen-res.py @@ -0,0 +1,6 @@ +#!/usr/bin/env python3 + +import sys + +with open(sys.argv[1], 'r') as infile, open(sys.argv[2], 'w') as outfile: + outfile.write(infile.read().format(icon=sys.argv[3])) diff --git a/test cases/windows/13 resources with custom targets/res/meson.build b/test cases/windows/13 resources with custom targets/res/meson.build new file mode 100644 index 000000000..266e3800e --- /dev/null +++ b/test cases/windows/13 resources with custom targets/res/meson.build @@ -0,0 +1,13 @@ +win = import('windows') + +rc_writer = find_program('./gen-res.py') + +rc_target = custom_target('RC source file', + input : 'myres.rc.in', + output : 'myres.rc', + command : [rc_writer, '@INPUT@', '@OUTPUT@', files('sample.ico')], + install : false, + build_always : true) + +res = win.compile_resources(rc_target, + include_directories : inc) diff --git a/test cases/windows/13 resources with custom targets/res/myres.rc.in b/test cases/windows/13 resources with custom targets/res/myres.rc.in new file mode 100644 index 000000000..9bb045dbe --- /dev/null +++ b/test cases/windows/13 resources with custom targets/res/myres.rc.in @@ -0,0 +1,4 @@ +#include +#include"resource.h" + +ICON_ID ICON "{icon}" diff --git a/test cases/windows/13 resources with custom targets/res/sample.ico b/test cases/windows/13 resources with custom targets/res/sample.ico new file mode 100644 index 0000000000000000000000000000000000000000..24bd3d9e96da04d444ac2f6029995d73b5bbd25f GIT binary patch literal 9662 zcmc)QX_HpL2v~PZn#8=D2i*;sJM&}lgZ4aGE2>? zn3uu46Q0a-s^*CgEPKA6&V9NX=*Aw0sp;hF|D1FG&$axn>-yi_Rg6Xx{qNRWNBwur z=-)StMpunSqfODH(ZTS1zMrY7snL(|pOgPJG4Nx17y5bj7R80JWW2h*ASTC5EY#L~ z`?A9ady8k`o*$q6k9~~a6Z5jTB36yLvUNo)jh}@*d@b0Ay&<+imrJ@{9+wASSQ&it zadFr?IiCizpW7E~UKQ)(=C~zpi>Z8@ zd3?RLb#>ThznJ7PuU37gUiMuZTjKtBEPgfSiPl|lZ)^)b|0ZZAt~u@ZT=2|BuFwpyj$?pAIwjyQZ7Zei8eE4YuDKuSZ(x^Y(asqm@?j;71-i zL+&@ls!;Fgo^4fMK0OzQp5f!u_&Vh9al9EcqSc_6`val3?hYE$;liQDUF%`}VviWV zisNxCK8X)P{Ok|0zt;7kkcaCR zWud?H0zJh@P0&%NREZ{jZ@2iIcLhy2PB z_PXbDwoc}dX7-C?U8ps!oWbtJ=pFUcpLE|B?27A#@ydr8I}+yO==j=f-xk-##pC!_ zcWtKV{AK(p{tzDpt?0qFv+4TaL!aLs^iUIhr4Q&z&pq+;SQVFq{_&m}lb`*xc{v`5 zt)X7_T^0O29AeUE=0rU9(|{IcY*C1dU4HHTeaM-8Hg1k9LL9X89$obVzxKQsZ-*Mt zbZ^`hY>VmApqZT2jW0P^9}Paly(IYYp7-_Y`$2!RC?EN5j?3eM&_8zs9o1A0w0t4d zmF8^Dd^dINJu%5aJ%^ay>RMcCPZRHo-}~ZIlil%3m>Ie134X*(o5is*aZd7AFbGj`1Re|SQZzB8MrZahI)yg zFW35TW2}e^LmsO`4fck3=%Ro2gm|wBx`<(YY!A8V&nL$B{P}!()`!@~b2HKNVJ^)Z z9pz8kr-T0LV-HQ2h8d8T+N#xuaX9SP1LnnEIp~j#AujRIL@vLKn?g?y{p>x@*icKW z`>VsAncf-4zNlwQLhUxi1Hr!7u`l=)KmFB84fHBa?R_Uci%;TEJQ7<%+~Q}Se{tLy z@)jHI_2sm#t@hGJpU_9m^`d*vPy5}k`wK$v4>=F|=mT}OJ{GqJJ8CRne&l;g(EGjk z+c*}VhP)q&%|Tnf)lLrVtP8Q}o0TCyx(v4IOsfI+XT~lDpUZPw>&tv~5_Aa;k@ zks~{LP2Mz9uP5W(_%{9=e~jP7OCbmEt`4>E4xd(-jp^9W=;t91F=FO-q;b#aOY^lM z^uVLRpZ=w#e)vu74Ygh$_Aeg%bj`Qt4~ATi$3Mrv#h>EicsU*pKJ2A|TIfG<(c!dy z9_-Jxj^CjnJ2%Jn*cbeN5OmYSN8n~0SM&hM&dJP#1RJjAw#>y|gT5>N#Hy?Gd|Kq5Cgl(41`={XV{o z--etXiy`*mY&a`+{@SMo`btljQ~JtXoUg{)As01ZUtP_b`a6r3%oq18`iUNezxC6gi`eNR*GuE9@9DYXAN!eTzdF-O-mAh~+!McwH$x73 zOANch=lWvK9_qQ7HRs~FJ!sF4zWFweg}EJK-`2H05W~Eh%$LKgJouH1-gDjzx|uaS zbU60KEpbK6{QWrFcF*;u8BtU9Qa8OrZ#7WM7lIaST@&)1Q;*rU7jm5)wbvtN;>Do9 zIZ%V=!Yuk;oBrG7Oq)Fy|MJi~JL2UKGtH00f$-einI*k=USbzZw#2XY&VnKSuez3l znmdPR%kNn;*0Z688@r~lzI%Vnq1MO4tm@V2o@qVH&Y8L_^gdgI{&e;`iMYQB^*7Vz zdu{w!{F~b2%#yPnR7daci7hcbL#^jC_KEE2#T$aoFNO2Rxu^c}@!aS0#qV4*LmPtr z2gCdfGxS*3;=dvmeAX;P|LmDzHC-1wLcHR3cDx(=toK|8EV|;W=MZ*4gGRB)KL$;7Q4fIIH%6%*+YNdn__%0oR@Ee zxpVdpz2kd(UfueP9p3?Zh#hB;*yZqc_-?#Crh90}`+vJ;&+J_u=IfEryR@U(-WYt& z{5>(3&-OV7)ad$9Gd-hse1FM9FFq7%urkcSPpX6W!kNv6xzo4ed@2rw-nG*I)>x2c z?bAc{vPExpj>hL#47P-(;4dL1|4DrfYeZ8k&Zi($7 z_Gd!OpN!G7`@4$?e%6K<;Tku^ z*0?)%#KZAqJQdFeyB~!3KOWyZN4#@o=#6v6Kd!-&_FWNTqKn^0=<;5C82aeVcqM4I zH{`M>cEv+uoBv1^VAH%+L$on+7EcC`g;#Y%9;@bFm(27QU zv8%3fP#1Z<5&ZjXz`gTJjI>oR@z8>uL&1)iUF%El$i;hfQ6F=0UFgRjjeY2;_FfP} z4qLjuCunP)=*}nKW=+l2TYs7J&&Jp0MUM6kvCY=ob7$m%5U;sXOL05@^o?_ASu9BV zA^ve6P4?c!u`<@i&0*Hq*8}{DOAcZ^8ehfNVczAWPJ^b-7Vix8*x&Wzu`7NVG%~C7 z;%`+fjm5EG?a##O4Op!r2H=ighiV_e8}cGO}?$b#5Ym3IH z_fP7TbH#n;XMDs^6S~Poe?gp9&%}9Ym?OHL7VnvM|3B`FNiOu0j~MAWFs*0z=U>x* znfiWWYBc&`G<9lpY&1GK+R^_ot(ZuHgz(4Cr86NHFd&$3Z9t${Pguy{|d_U=`}y6Mmv7^tG~rbz;8c& tKCHzxeLubS`48?}i+d#QspGBbICZl1SZgoRd8&=atWzhJ_p93IzX4~+P{RNK literal 0 HcmV?d00001 From f8bd1c5ff26bbb6b88dedcb400a33841201bf4eb Mon Sep 17 00:00:00 2001 From: Andrei Alexeyev <0x416b617269@gmail.com> Date: Fri, 22 Dec 2017 20:16:56 +0200 Subject: [PATCH 2/4] windows.compile_resources: fix compiling multiple resources within one project --- mesonbuild/modules/windows.py | 40 +++++++++++++++---- .../inc/meson.build | 1 - .../inc/resource/resource.h | 1 - .../meson.build | 11 ++--- .../res/meson.build | 23 ++++++----- .../res/myres.rc.in | 3 +- .../res/myres_static.rc | 3 ++ 7 files changed, 57 insertions(+), 25 deletions(-) delete mode 100644 test cases/windows/13 resources with custom targets/inc/meson.build delete mode 100644 test cases/windows/13 resources with custom targets/inc/resource/resource.h create mode 100644 test cases/windows/13 resources with custom targets/res/myres_static.rc diff --git a/mesonbuild/modules/windows.py b/mesonbuild/modules/windows.py index 22bf49b2a..dc6e9d8bc 100644 --- a/mesonbuild/modules/windows.py +++ b/mesonbuild/modules/windows.py @@ -68,15 +68,41 @@ class WindowsModule(ExtensionModule): if not rescomp.found(): raise MesonException('Could not find Windows resource compiler %s.' % ' '.join(rescomp.get_command())) - res_kwargs = { - 'output': '@BASENAME@.' + suffix, - 'input': args, - 'command': [rescomp] + res_args, - } + res_targets = [] - res_target = build.CustomTarget('Windows resource', state.subdir, state.subproject, res_kwargs) + def add_target(src): + if isinstance(src, list): + for subsrc in src: + add_target(subsrc) + return - return ModuleReturnValue(res_target, [res_target]) + if hasattr(src, 'held_object'): + src = src.held_object + + res_kwargs = { + 'output': '@BASENAME@.' + suffix, + 'input': [src], + 'command': [rescomp] + res_args, + } + + if isinstance(src, (str, mesonlib.File)): + name = 'file {!r}'.format(str(src)) + elif isinstance(src, build.CustomTarget): + if len(src.get_outputs()) > 1: + raise MesonException('windows.compile_resources does not accept custom targets with more than 1 output.') + + name = 'target {!r}'.format(src.get_id()) + else: + raise MesonException('Unexpected source type {!r}. windows.compile_resources accepts only strings, files, custom targets, and lists thereof.'.format(src)) + + # Path separators are not allowed in target names + name = name.replace('/', '_').replace('\\', '_') + + res_targets.append(build.CustomTarget('Windows resource for ' + name, state.subdir, state.subproject, res_kwargs)) + + add_target(args) + + return ModuleReturnValue(res_targets, [res_targets]) def initialize(): return WindowsModule() diff --git a/test cases/windows/13 resources with custom targets/inc/meson.build b/test cases/windows/13 resources with custom targets/inc/meson.build deleted file mode 100644 index b8b511a98..000000000 --- a/test cases/windows/13 resources with custom targets/inc/meson.build +++ /dev/null @@ -1 +0,0 @@ -inc = include_directories('resource') diff --git a/test cases/windows/13 resources with custom targets/inc/resource/resource.h b/test cases/windows/13 resources with custom targets/inc/resource/resource.h deleted file mode 100644 index dbdd5094d..000000000 --- a/test cases/windows/13 resources with custom targets/inc/resource/resource.h +++ /dev/null @@ -1 +0,0 @@ -#define ICON_ID 1 diff --git a/test cases/windows/13 resources with custom targets/meson.build b/test cases/windows/13 resources with custom targets/meson.build index ddb7d6e8a..b1e2b091b 100644 --- a/test cases/windows/13 resources with custom targets/meson.build +++ b/test cases/windows/13 resources with custom targets/meson.build @@ -59,11 +59,12 @@ if meson.get_compiler('c').get_id() == 'gcc' and host_machine.system() == 'windo # We hope you never have to implement something like this. endif -subdir('inc') subdir('res') -exe = executable('prog', 'prog.c', - res, - gui_app : true) +foreach id : [0, 1, 2] + exe = executable('prog_@0@'.format(id), 'prog.c', + res[id], + gui_app : true) -test('winmain', exe) + test('winmain_@0@'.format(id), exe) +endforeach diff --git a/test cases/windows/13 resources with custom targets/res/meson.build b/test cases/windows/13 resources with custom targets/res/meson.build index 266e3800e..c15bd92d2 100644 --- a/test cases/windows/13 resources with custom targets/res/meson.build +++ b/test cases/windows/13 resources with custom targets/res/meson.build @@ -2,12 +2,17 @@ win = import('windows') rc_writer = find_program('./gen-res.py') -rc_target = custom_target('RC source file', - input : 'myres.rc.in', - output : 'myres.rc', - command : [rc_writer, '@INPUT@', '@OUTPUT@', files('sample.ico')], - install : false, - build_always : true) - -res = win.compile_resources(rc_target, - include_directories : inc) +rc_sources = [] + +foreach id : [1, 2] + rc_sources += custom_target('RC source file @0@'.format(id), + input : 'myres.rc.in', + output : 'myres_@0@.rc'.format(id), + command : [rc_writer, '@INPUT@', '@OUTPUT@', files('sample.ico')], + install : false, + build_always : true) +endforeach + +rc_sources += files('myres_static.rc') + +res = win.compile_resources(rc_sources) diff --git a/test cases/windows/13 resources with custom targets/res/myres.rc.in b/test cases/windows/13 resources with custom targets/res/myres.rc.in index 9bb045dbe..6899bc8f3 100644 --- a/test cases/windows/13 resources with custom targets/res/myres.rc.in +++ b/test cases/windows/13 resources with custom targets/res/myres.rc.in @@ -1,4 +1,3 @@ #include -#include"resource.h" -ICON_ID ICON "{icon}" +1 ICON "{icon}" diff --git a/test cases/windows/13 resources with custom targets/res/myres_static.rc b/test cases/windows/13 resources with custom targets/res/myres_static.rc new file mode 100644 index 000000000..12838aee2 --- /dev/null +++ b/test cases/windows/13 resources with custom targets/res/myres_static.rc @@ -0,0 +1,3 @@ +#include + +1 ICON "sample.ico" From 46f5d7a31c122809096183a1ead210f6b4f8b18f Mon Sep 17 00:00:00 2001 From: Andrei Alexeyev <0x416b617269@gmail.com> Date: Fri, 12 Jan 2018 23:40:11 +0200 Subject: [PATCH 3/4] Fix test cases/windows/13 resources with custom targets Analogous to #2851 --- test cases/windows/13 resources with custom targets/prog.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test cases/windows/13 resources with custom targets/prog.c b/test cases/windows/13 resources with custom targets/prog.c index 2c6f1535d..2bef6a278 100644 --- a/test cases/windows/13 resources with custom targets/prog.c +++ b/test cases/windows/13 resources with custom targets/prog.c @@ -9,6 +9,6 @@ WinMain( LPSTR lpszCmdLine, int nCmdShow) { HICON hIcon; - hIcon = LoadIcon(NULL, IDI_APPLICATION); + hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(MY_ICON)); return hIcon ? 0 : 1; } From fd4236085bf3852f783e0b6df758365093d3b000 Mon Sep 17 00:00:00 2001 From: Andrei Alexeyev <0x416b617269@gmail.com> Date: Fri, 12 Jan 2018 23:48:49 +0200 Subject: [PATCH 4/4] Add a release note snippet for the windows.compile_resources() change --- docs/markdown/snippets/windows-resources-custom-targets.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 docs/markdown/snippets/windows-resources-custom-targets.md diff --git a/docs/markdown/snippets/windows-resources-custom-targets.md b/docs/markdown/snippets/windows-resources-custom-targets.md new file mode 100644 index 000000000..a2dce3ad1 --- /dev/null +++ b/docs/markdown/snippets/windows-resources-custom-targets.md @@ -0,0 +1,3 @@ +## Can use custom targets as Windows resource files + +The `compile_resources()` function of the `windows` module can now be used on custom targets as well as regular files.