Author Topic: Global variables and buid targets  (Read 9569 times)

Offline cacb

  • Lives here!
  • ****
  • Posts: 536
Global variables and buid targets
« on: December 06, 2013, 11:12:03 pm »
I have used C::B with wx2.8 for some years and now I am looking into upgrading to wx3.0. The basics of my setup is that I use the MSVC 2010 compiler on Windows and gcc on Linux Kubuntu.  Therefore, all my projects have 4 build targets, i.e.
Quote
Windows: MSVC_Release &  MSVC_Debug   
Linux: GCC_Release & GCC_Debug   

I build wxWidgets myself, as static libraries on both platforms, and I have a lot of C::B projects that needs to be upgraded. For wx2.8, I have created a global variable 'wx',  defined as
Quote
Windows: BASE = E:\CPDE2\zdep\3rdparty\wx2.8.12
Linux: BASE = /usr/local
and nothing else

For each project, my MSVC build targets have some additional build option settings under
MSVC_Debug:
'Search directories'/Compiler: $(#wx)\lib\vc_lib\mswd
'Search directories'/Linker: $(#wx)\lib\vc_lib
'Search directories'/Resource Compiler: $(#wx)\lib\vc_lib\mswd

MSVC_Release:
'Search directories'/Compiler: $(#wx)\lib\vc_lib\msw
'Search directories'/Linker: $(#wx)\lib\vc_lib
'Search directories'/Resource Compiler: $(#wx)\lib\vc_lib\msw

As you can see, there are subtle differences in the include paths between MSVC debug and release targets. Since I will need to upgrade my project files when moving to wx3.0 anyway, I am wondering if there is any way I can use global variables in a smarter way than currently so that I don't have to maintain these details in every project file, but hide them away in the global variables settings.

The global variables have fields for include, allowing me to write $(#wx.include) in the project, but the problem is that the include paths are different for Debug and Release build targets, so it won't work.

What is the best way to deal with this problem? Would it be to define two user-defined fields (for example 'include_debug' and 'include_release') and let them point to $(#wx)\lib\vc_lib\msw and $(#wx)\lib\vc_lib\mswd respectively, or is there some other and better way?


Offline MortenMacFly

  • Administrator
  • Lives here!
  • *****
  • Posts: 9694
Re: Global variables and buid targets
« Reply #1 on: December 07, 2013, 07:58:54 am »
For each project, my MSVC build targets have some additional build option settings under
MSVC_Debug:
'Search directories'/Compiler: $(#wx)\lib\vc_lib\mswd
'Search directories'/Linker: $(#wx)\lib\vc_lib
'Search directories'/Resource Compiler: $(#wx)\lib\vc_lib\mswd
MSVC_Release:
'Search directories'/Compiler: $(#wx)\lib\vc_lib\msw
'Search directories'/Linker: $(#wx)\lib\vc_lib
'Search directories'/Resource Compiler: $(#wx)\lib\vc_lib\msw
Hmmm - I don't quite see what your problem is, but you could use the additional (user-defined) field of a GCV to use different include path's or just make two different GCV's - one for WX30 and one for WX28 (that's how we do it in C::B, for example).
Compiler logging: Settings->Compiler & Debugger->tab "Other"->Compiler logging="Full command line"
C::B Manual: https://www.codeblocks.org/docs/main_codeblocks_en.html
C::B FAQ: https://wiki.codeblocks.org/index.php?title=FAQ

Offline cacb

  • Lives here!
  • ****
  • Posts: 536
Re: Global variables and buid targets
« Reply #2 on: December 07, 2013, 11:29:57 am »
Hmmm - I don't quite see what your problem is, but you could use the additional (user-defined) field of a GCV to use different include path's or just make two different GCV's - one for WX30 and one for WX28 (that's how we do it in C::B, for example).

It isn't about wx2.8 versus wx3.0. I have started a (hopefully short) transition process and will abandon wx2.8 as soon as I am confident wx3.0 causes me no problems.

The main points are
a) I want, if possible, to remove compiler-specific configuration info from the project files (*.cbp) and keep it in global variables. That's what global variables are for I believe. After all, I have only as many definitions of 'wx' as I have installations of C::B (i.e. less than 5), but I have a large number of C::B project files (50+) where this info is repeated over and over, sometimes with bugs.

b) The problem with global variables in this case seems to be that it ignores the issue of build targets. As I showed, the include paths are different for debug and release targets when using the MSVC compiler. This is true for both wx2.8 and wx3.0, so having different global variables for 2.8 and 3.0 does not solve this particular issue.

I did some experimentation with user defined fields (i.e. fields 'msvc_include_release' and 'msvc_include_debug' as user defined fields for the 'wx' global variables), and it does indeed work. So a slight improvement is indeed possible, but I was looking for something more that could simplify my *.cbp files even further. In this process I found that the user defined fields in C::B are largely broken (I am using a recent C::B nightly) for anything else than very simple use. If you try to define more than 3 user defined fields, strange things start to happen (The BASE field gets overwritten for example).

related side-issue:
A related issue which is completely ignored by the global variables is the list of libraries to be provided to the linker (both wx-libraries and ms libraries). There is no wx-config when using MSVC unless I am mistaken. So I have to repeat everything (library names+linker options) explicitely for every build target in every project file (except for the GCC targets where I use wx-config). If the global variables could accommodate partially the information that goes into the <Linker> section of the *.cbp files, much could be saved. Alternatively. would it be possible for me to achieve something similar if I created an equivalent to wx-config and used the 'bacticks' option to specify linker libraries and options? I mean under Windows, using the MSVC compiler?

EDIT: I did some experiments on windows and it seems `backtics`  may be a possible way forward for the linker issue at least.
I also found wx-config for Windows, which seems interesting.
« Last Edit: December 07, 2013, 02:54:59 pm by cacb »

Offline cacb

  • Lives here!
  • ****
  • Posts: 536
Re: Global variables and buid targets
« Reply #3 on: December 07, 2013, 11:58:26 pm »
Just a follow up to the above: I seem to have reached a preliminary conclusion on how to simplify the project setup when compiling under MSVC on Windows, in a way that makes it similar to Linux. Regarding use of global variables, I have reverted to only defining the BASE member for my 'wx' global variable, and it is even questionable if it is needed at all, as in this case it is only used in the resource compiler.

The best solution seems to be to use the Windows port of the wx-config utility. This port is some years old, and I found a bug in it (it always returns debug libraries, even for release builds). I found a fix for that, so if anyone is interested (not sure how to upload a fix to the original site). After fixing the bug, all I need to do is define an environment variable WXWIN that points to the wxWidgets install directory, so wx-config can find it. I prefer to do it inside Code::Blocks and it works fine.

The options in the windows port of wx-config are in reality a bit different from Linux, as you have to use the --wxcfg option to point to the relevant build configuration of wxWidgets. That enables wx-config to read the relevant build.cfg file which really contains the essentials. So it isn't really required to be explicit about debug=yes/no static=yes/no etc.

Below is the complete setup for the MSVC_Debug build target that I used for a test GUI application. This is far simpler than what I have used with wx2.8 before, so I think it could be nice to introduce this type of setup as I move to wx3.0

Quote
<Target title="MSVC_Debug">
   <Option output=".cmp/msvc/bin/Debug/wx3Dialog1" prefix_auto="0" extension_auto="1" />
   <Option object_output=".cmp/msvc/obj/Debug/" />
   <Option type="0" />
   <Option compiler="msvc" />
   <Option projectLinkerOptionsRelation="2" />
   <Compiler>
      <Add option="/MDd" />
      <Add option="/Od" />
      <Add option="/GF" />
      <Add option="/EHsc" />
      <Add option="/W3" />
      <Add option="/RTCsu" />
      <Add option="/Fd$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).pdb" />
      <Add option="/D_CRT_SECURE_NO_WARNINGS" />
      <Add option="/D_CRT_NONSTDC_NO_DEPRECATE" />
      <Add option="/D_CRT_SECURE_DEPRECATE" />
      <Add option="`wx-config --wxcfg=vc_lib\mswud --cxxflags`" />
   </Compiler>
   <Linker>
      <Add option="/DEBUG" />
      <Add option="/NODEFAULTLIB:libcmt.lib" />
      <Add option="/NODEFAULTLIB:msvcrt.lib" />
      <Add option="`wx-config --wxcfg=vc_lib\mswud --libs`" />
      <Add library="msvcrtd.lib" />
   </Linker>
</Target>

Here is the complete setup for the MSVC_Release build target

Quote
<Target title="MSVC_Release">
   <Option output=".cmp/msvc/bin/Release/wx3Dialog1" prefix_auto="0" extension_auto="1" />
   <Option object_output=".cmp/msvc/obj/Release/" />
   <Option type="0" />
   <Option compiler="msvc" />
   <Option projectLinkerOptionsRelation="2" />
   <Compiler>
      <Add option="/MD" />
      <Add option="/Ox" />
      <Add option="/GF" />
      <Add option="/EHsc" />
      <Add option="/W3" />
      <Add option="/D_CRT_SECURE_NO_WARNINGS" />
      <Add option="/D_CRT_NONSTDC_NO_DEPRECATE" />
      <Add option="/D_CRT_SECURE_DEPRECATE" />
      <Add option="`wx-config --wxcfg=vc_lib\mswu --cxxflags`" />
   </Compiler>
   <Linker>
      <Add option="/NODEFAULTLIB:libcmtd.lib" />
      <Add option="/NODEFAULTLIB:msvcrtd.lib" />
      <Add option="/INCREMENTAL:NO" />
      <Add option="`wx-config --wxcfg=vc_lib\mswu --libs`" />
      <Add library="msvcrt.lib" />
   </Linker>
</Target>

EDIT: The simplification revealed some bugs, now fixed
« Last Edit: December 08, 2013, 11:04:22 pm by cacb »

Offline cacb

  • Lives here!
  • ****
  • Posts: 536
Re: Global variables and buid targets
« Reply #4 on: December 17, 2013, 11:38:59 pm »
Hi,

I thought I would do a small update on the way Code::Blocks can be configured to build the same software using different operating systems and compilers, and also different versions of wxWidgets, without changing anything in the project setup.

In the examples below, I am able to build using MSVC 2010 (express of full version) on Windows and GCC on Linux, using the same project files. One can also switch between wxWidgets 2.8.12 and wxWidgets 3.0.0 easily.

To achieve this, I use the 'backticks' facility that is supported in Code::Blocks, and use two different versions of wx-config to provide compiler settings and wx libraries. On Linux, it is the standard wx-config that comes with wxWidgets, and on Windows I use a modified version of a Windows-port of wx-config. The wx-config programs serve the same purpose, but they take different parameters.

The second feature that is important is Code::Blocks global variables. On both Windows and Linux I use a global variable 'wx' with a BASE member that points to the wxWidgets installation. As I build wxWidgets (as static libraries) myself, this means that, on Linux, the 'wx' global variable points to /usr/local. On Windows this is a bit different, as the 'wx' variable points to the root of the wxWidgets 2.8.12 installation or wxWidgets 3.0.0, depending on what I am using at the moment. Since I am using the MSVC compiler on Windows, I get vc_lib\mswd and vc_lib\msw subfolders under 'lib' for debug and release (ANSI) under 2.8.12. Under 3.0.0 I am using unicode builds, so in that case the subfolders become vc_lib\mswud and vc_lib\msuw instead.

I found it convenient to define two user defined fields ('debug' and 'release') for the 'wx' global variable under Windows, and assign the subfolder paths as mentioned above.

Windows (MSVC)

For wxWidgets 2.8.12, my Windows 'wx' global variable is defined as shown in msw28.gif.
For wxWidgets 3.0.0, my Windows 'wx' global variable is defined as shown in msw30.gif, notice the base path and unicode options.

Given these settings, I can define a Windows msvc debug target as follows

Quote
<Target title="MSVC_Debug">
   <Option output=".cmp/msvc/bin/Debug/myprogd" prefix_auto="0" extension_auto="1" />
   <Option object_output=".cmp/msvc/obj/Debug/" />
   <Option type="0" />
   <Option compiler="msvc" />
   <Option projectLinkerOptionsRelation="2" />
   <Compiler>
      <Add option="/MDd" />
      <Add option="/Od" />
      <Add option="/RTCsu" />
      <Add option="/GF" />
      <Add option="/EHsc" />
      <Add option="/W3" />
      <Add option="`wx-config.exe --prefix=$(#wx) --wxcfg=$(#wx.debug) --cxxflags`" />
      <Add option="/Fd$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).pdb" />
      <Add option="/D_CRT_SECURE_NO_WARNINGS" />
      <Add option="/D_CRT_NONSTDC_NO_DEPRECATE" />
      <Add option="/D_CRT_SECURE_DEPRECATE" />
   </Compiler>
   <ResourceCompiler>
      <Add directory="$(#wx)/include" />
   </ResourceCompiler>
   <Linker>
      <Add option="`wx-config.exe --prefix=$(#wx) --wxcfg=$(#wx.debug) --libs`" />
      <Add option="/SUBSYSTEM:WINDOWS" />
      <Add option="/NODEFAULTLIB:libcmt.lib" />
      <Add option="/NODEFAULTLIB:msvcrt.lib" />
      <Add option="/INCREMENTAL:NO" />
      <Add library="msvcrtd.lib" />
   </Linker>
</Target>

Similarly, a release target for Windows msvc

Quote
<Target title="MSVC_Release">
   <Option output=".cmp/msvc/bin/Release/myprog" prefix_auto="0" extension_auto="1" />
   <Option object_output=".cmp/msvc/obj/Release/" />
   <Option type="0" />
   <Option compiler="msvc" />
   <Option projectLinkerOptionsRelation="2" />
   <Compiler>
      <Add option="/MD" />
      <Add option="/GF" />
      <Add option="/Ox" />
      <Add option="/W3" />
      <Add option="/EHsc" />
      <Add option="`wx-config.exe --prefix=$(#wx) --wxcfg=$(#wx.release) --cxxflags`" />
      <Add option="/D_CRT_SECURE_NO_WARNINGS" />
      <Add option="/D_CRT_NONSTDC_NO_DEPRECATE" />
      <Add option="/D_CRT_SECURE_DEPRECATE" />
   </Compiler>
   <ResourceCompiler>
      <Add directory="$(#wx)/include" />
   </ResourceCompiler>
   <Linker>
      <Add option="`wx-config.exe --prefix=$(#wx) --wxcfg=$(#wx.release) --libs`" />
      <Add option="/SUBSYSTEM:WINDOWS" />
      <Add option="/NODEFAULTLIB:libcmtd.lib" />
      <Add option="/NODEFAULTLIB:msvcrtd.lib" />
      <Add option="/INCREMENTAL:NO" />
      <Add library="msvcrt.lib" />
   </Linker>
   <ExtraCommands>
      <Add after="mt.exe /nologo /manifest $(TARGET_OUTPUT_FILE).manifest /outputresource:$(TARGET_OUTPUT_FILE);1" />
      <Add after="$(CPDE_USR)\bin\cpde_usr -bin -xi -project=$(PROJECT_NAME)  -root=$(PROJECT_DIR)  -build=$(TARGET_NAME)  -target=$(TARGET_OUTPUT_FILE)  -usr=$(CPDE_USR)" />
   </ExtraCommands>
</Target>



Linux

On Linux the wx-config program is a bit different from the Windows port, so the definition of the 'wx' variable is also a bit different from Windows. Instead of 'debug' and 'release' user defined fields, I define just a single 'config' field wich has a definition that ensures the proper wx-config is run, plus it sets the option for using wx2.8 or wx3.0 (since thebase path is the same for both in this case). Debug or release options are instead 'hard-coded' in their respective targets as shown below. Notice I build unicode for both 2.8.12 and 3.0.0 under Linux.

For wxWidgets 2.8.12, my Linux 'wx' global variable is defined as shown in gtk28.gif  (see next post)
For wxWidgets 2.8.12, my Linux 'wx' global variable is defined as shown in gtk30.gif  (see next post)

Given these settings, I can define a Linux gcc debug target as follows

Quote
<Target title="GCC_Debug">
   <Option output=".cmp/gcc/bin/Debug/myprog" prefix_auto="0" extension_auto="1" />
   <Option object_output=".cmp/gcc/obj/Debug/" />
   <Option type="0" />
   <Option compiler="gcc" />
   <Option projectLinkerOptionsRelation="2" />
   <Compiler>
      <Add option="-std=c++0x" />
      <Add option="-g" />
      <Add option="-W" />
      <Add option="-fPIC" />
      <Add option="-fexceptions" />
      <Add option="`$(#wx.config) --cxxflags --debug`" />
      <Add option="-DNOPCH" />
      <Add option="-D_DEBUG" />
   </Compiler>
   <Linker>
      <Add option="`$(#wx.config) --libs std,aui  --static --debug`" />
   </Linker>
</Target>

Similarly, a release target for Linux gcc

Quote
<Target title="GCC_Release">
   <Option output=".cmp/gcc/bin/Release/myprog" prefix_auto="0" extension_auto="1" />
   <Option object_output=".cmp/gcc/obj/Release/" />
   <Option type="0" />
   <Option compiler="gcc" />
   <Option projectLinkerOptionsRelation="2" />
   <Compiler>
      <Add option="-Os" />
      <Add option="-std=c++0x" />
      <Add option="-W" />
      <Add option="-fPIC" />
      <Add option="-fexceptions" />
      <Add option="`$(#wx.config) --cxxflags`" />
      <Add option="-DNOPCH" />
   </Compiler>
   <Linker>
      <Add option="-s" />
      <Add option="`$(#wx.config) --libs std,aui --static`" />
   </Linker>
   <ExtraCommands>
      <Add before="rm -f $(TARGET_OUTPUT_FILE)" />
      <Add after="upx $(TARGET_OUTPUT_FILE)" />
      <Add after="$(CPDE_USR)/bin/cpde_usr -bin -xi -project=$(PROJECT_NAME)  -root=$(PROJECT_DIR)  -build=$(TARGET_NAME)  -target=$(TARGET_OUTPUT_FILE)  -usr=$(CPDE_USR)" />
      <Mode after="always" />
   </ExtraCommands>
</Target>


In the above, I have removed some other (private) libraries that I am using, these examples are meant as illustration of settings relevant for the configuration of wxWidgets. It is worth observing that it is very nice that global variables may be evaluated within the backtics area, the last time I tried it (some years ago) it wasn't available.

Finally, it should be noted that the different values for the global variables are stored in different Sets in the global variable editor. To switch between wxWidgets 2.8 and 3.0, all I have to do is switch the current global variable set. It is easy to get confused here, so perhaps the name of the global variable set could be prominently visible somewhere (in the main windows header  or status bar perhaps?).

In experimenting with these things, I experienced quite a few code::block crashes, and I learned that project settings are never saved until you exit Code::Bloks, so you lose the settings if you suffer a crash. It would be nice to have some feature wich actually did save everything without requiring a complete exit/restart of Code::Blocks.

Another thing I noticed (on a relatively slow XP computer running nightly build 9455), was that when you load a workspace with several projects after switching the global variable current set, a 'massive' reparsing of the files takes place and the IDE spends 15-20 seconds processing heavily. If you don't lay off the mouse in this period, but try a 'rebuild all' for example, you are almost certain to suffer either an immediate crash or an infinite hang (thread race condition?) that must be killed in Task Manager.

Still, whith these minor issues, Code::Blocks is extremely configurable and nice to work with-
« Last Edit: December 17, 2013, 11:49:06 pm by cacb »

Offline cacb

  • Lives here!
  • ****
  • Posts: 536
Re: Global variables and buid targets
« Reply #5 on: December 17, 2013, 11:41:09 pm »
Additional attachments for Linux build targets. Please refer to the post above.