Author Topic: How to specify different GCC compiler arguments between C and C++?  (Read 6056 times)

boo

  • Community Member
  • Posts: 16
  • Hero Points: 0
I've got C and C++ mixed code in one GCC project. One toy example I can share is that I need to compile C files with --std=c99 and not apply this to the C++ files and vice versa. Creating a new project isn't the easiest solution given the significant amount work to synchronize the other 99% settings (non-compiler related) between them. Is there any way to have the GNU C Options allow one compiler settings for C and one compiler settings for C++? That would be an extremely useful tool to me and my engineers.

Thanks,
Boo

Graeme

  • Senior Community Member
  • Posts: 2682
  • Hero Points: 335
Re: How to specify different GCC compiler arguments between C and C++?
« Reply #1 on: August 09, 2009, 11:36:43 am »
I think the only way to do this is to modify a slick macro file - it's fairly safe though and not too hard, if it works at all!

If you look at the _parse_project_command in the compile.e module in the slick macro folder and turn on selective display, you'll see this

Code: [Select]
      } else if ( ch=='Q' ) {
      } else if (ch=='D') {
      } else if ( ch=='F' ) {
      } else if ( ch=='N' ) {
      } else if ( ch=='M') {
      // etc

If you look up _parse_project_command in slick help, you'll see what all the %expansions mean. e.g. %N is filename without extension or path.  %F is absolute filename.  %M is an undocumented switch  -you can see where I described it here http://community.slickedit.com/index.php?topic=1155.0.  It allows you to call a slick macro and embeds the string returned by your macro in the command line passed to the compiler (best not to have any % characters in the string returned - or else use %% - need to test this!).

You could modify the code that handles the %M switch to pass the name of the file being compiled, to your macro as an additional parameter.  The code that handles %M looks like this

Code: [Select]
      } else if ( ch=='M') {
         k= pos('[A-Za-z0-9_]',command,j+2,'r');
         if (!k) {
            return(command);
         }
         int l= pos('%',command,k);
         if (!l) {
            return(command);
         }
         int w= l-k;
         _str macCommand= sub_str(command,k,w);
         //messageNwait("macName "macName);
         _str fctname,cmdline;
         parse macCommand with fctname cmdline;
         int index=find_index(fctname,PROC_TYPE|COMMAND_TYPE);
         if (!index) {
            _message_box(nls('Function %s1 not found',fctname));
         } else {
            s=call_index(cmdline,index);
            len= l-j+1;
         }

If you use the %M switch, you do it like this (_config_path is the name of a slick macro function that returns a string)
%M _config_path%
or to pass a parameter to your macro
%M my_macro hello%

If you change the line s=call_index in the code that handles %M above to the following
s=call_index(cmdline, buf_name, index);

then the name of the buffer being compiled gets passed to your macro as an extra parameter.

You could then write a slick macro like this

Code: [Select]
_command _str my_macro(_str cmdline = '', _str bufname = '') name_info(',')
{
   _str ext = upcase(get_extension(bufname));
   switch (ext) {
      default:
      case 'CPP' : return '-std=c++0x';
      case 'C' : return '--std=c99';
   }
   return '';
}

_command void test_my_macro() name_info(',')
{
   _message_box(my_macro('', 'f1.c'));
   _message_box(my_macro('', 'f1.cpp'));
   _message_box(my_macro('', 'f1.cc'));
}

If you want to try it, copy the code for my_macro above, to vusrmac.e in your configuration folder and load it using the load module command on the macro menu.

To modify the _parse_project_command function, copy the file compile.e to a folder of your own (e..g your config folder), then edit it and change the call_index line, then load it using the load module command again.  If you want to revert to the original compile.e module, open compile.e from the installation macro folder and load it using the load module command again.

If you don't have a vusrmac.e file, record a trivial macro and save it and vusrmac.e should be created.

Dunno if this'll work for you but it shouldn't be hard to try it.

Graeme

Lee

  • SlickEdit Team Member
  • Senior Community Member
  • *
  • Posts: 1299
  • Hero Points: 130
Re: How to specify different GCC compiler arguments between C and C++?
« Reply #2 on: August 10, 2009, 01:16:25 pm »
There is a way to set separate compile rules up for different extensions, but unfortunately it's not directly configurable through Project Properties or any GUI in SlickEdit.  It does requires modifying the project file (.vpj) directly.  They are XML files, so it's straightforward to make modifications, and follows a fairly logical structure.  I've attached an example which does this you can use a reference, and I'll explain what you'll need to do.  You'll see that the project file layout is something like this:
<Project>
    <Config> ... </Config>
    <Config> ... </Config>
    <Files> ... </Files>
</Project>

There will be a <Config> for each named configuration in your project (Debug, Release, ...).  What you are going to want to do in each <Config> tag, you will want to add a <Rules> tag.  You can specify specific command-line for an extension type for a specific target in your build tool list, example:
      <Rules Name="Compile">
         <Rule
            InputExts="*.c"
            OutputExts="*.o">
            <Exec CmdLine='gcc -c -g --std=c99 -o "%bd%n%oe" %i "%f"'/>
         </Rule>
      </Rules>

You'll want to a Rule for each config so you have the debugging or optimization options appropriately set.  You are also allowed to have a single Rule at the <Project> level and only have a single command-line for all configurations.  We typically use Rules this way for Windows Resource files (.rc) or to compile message lists which do not differ from Debug to Release configurations.

If this doesn't work you, then you may have to dropback to maintaining your own makefile or custom build script that handles the options, and set your Build command to execute your custom build.

boo

  • Community Member
  • Posts: 16
  • Hero Points: 0
Re: How to specify different GCC compiler arguments between C and C++?
« Reply #3 on: August 11, 2009, 11:21:46 am »
This is very nice already. I might be pushing my luck here but do these xml rules extend to per file or directory too? The possibilities of suppressing warnings per file would be pretty cool.

Lee

  • SlickEdit Team Member
  • Senior Community Member
  • *
  • Posts: 1299
  • Hero Points: 130
Re: How to specify different GCC compiler arguments between C and C++?
« Reply #4 on: August 11, 2009, 02:07:40 pm »
No, <Rule> is only applies to extensions.  We've had requests for per-file build rules, it would be nice to have.  I'll add your vote for that feature to the list.

TurkeyMan

  • Community Member
  • Posts: 22
  • Hero Points: 0
Re: How to specify different GCC compiler arguments between C and C++?
« Reply #5 on: September 14, 2015, 05:12:44 am »
Any movement on this in the last 6 years?
I am building Qt projects, and I need to run Moc on select header files, shaders that need to be compiled into .h files, embedded assets that need conversion to .h files, and resource files which need to be compiled.
I think file-specific rules would be the natural way to do this. Possibility of custom per-file build rules?

TurkeyMan

  • Community Member
  • Posts: 22
  • Hero Points: 0
Re: How to specify different GCC compiler arguments between C and C++?
« Reply #6 on: September 14, 2015, 07:03:53 am »
Another addendum, I have used <Rules> to compile .qrc files, which produce .cpp files which must then be compiled.
I am seeing that the rule is indeed executed first before the .cpp files are compiled, which is necessary, but in order to build the generated qrc.cpp file, it needs to be a file in the project...
So I put the expected generated qrc.cpp file in the <Files>, but this creates a problem where the build process doesn't begin with an error that the .cpp file (that will be generated) doesn't exist. So, it seems to validate that all .cpp files referenced in <Files> exist before beginning the build process. This seems to be a chicken-and-egg problem; qrc.cpp doesn't exist, so it won't be generated.

Suggest; create some method to inhibit this validation step. There are far too many situations where source files are generated prior to compiling.

Clark

  • SlickEdit Team Member
  • Senior Community Member
  • *
  • Posts: 6126
  • Hero Points: 470
Re: How to specify different GCC compiler arguments between C and C++?
« Reply #7 on: September 15, 2015, 04:05:03 am »
In regard to Qt builds, we do some very custom building with vsbuild for our Qt builds. If it weren't so different from Qt projects we would ship it. Like Lee says, the GUI doesn't support all the VPJ features.

TurkeyMan

  • Community Member
  • Posts: 22
  • Hero Points: 0
Re: How to specify different GCC compiler arguments between C and C++?
« Reply #8 on: September 20, 2015, 05:00:12 am »
That's interesting to hear about. Perhaps like I asked in my other thread (which didn't get any replies), it would be worth documenting everything expressible in the .vpj file, so then we may have more power available to flesh out our build solutions?

I'd love to see what you're doing for Qt, and if that can be expanded for our other uses too.