setting compiler options programmatically.

I am trying to simplify my life and set up all compiler options programmatically in a single file where I will see what is going on. I created a .cpp file and copied an MSDN function in there that is supposed to do it. My intention is to call this function eventually from the main routine. So far all attempts to compile the file failed with the errors described below. First the code:

using namespace System;
using namespace System::Object;
using namespace System::CodeDom;
using namespace System::CodeDom::Compiler;
using namespace System::CodeDom::Compiler::CodeDomProvider;
using namespace System::String;
using namespace System::Object::Microsoft::VisualC::CodeDomTypeInfo;
#include <stdafx.h>
#include "unknwn.h"
#include <winternl.h>

static bool CompileCode( CodeDomProvider^ provider,
   String^ sourceFile,
   String^ exeFile )

   // Obtain an ICodeCompiler from a CodeDomProvider class.      
   ICodeCompiler^ compiler = provider->CreateCompiler();

   CompilerParameters^ cp = gcnew CompilerParameters;
   if ( ( !cp) || ( !compiler) )
   {
...............

<the rest is immaterial>

These are the errors:
Error 1 error C2065: 'CodeDomProvider' : undeclared identifier 
Error 2 error C2065: 'provider' : undeclared identifier 
Error 3 error C2065: 'String' : undeclared identifier 
Error 4 error C2065: 'sourceFile' : undeclared identifier 
Error 5 error C2065: 'exeFile' : undeclared identifier 
Error 6 error C2448: 'CompileCode' : function-style initializer appears to be a function definition 

Errors 2,4 & 5 are self explainatory. What about CodeDomProvider and String, they should be predefined names




Answer this question

setting compiler options programmatically.

  • Stephen Patten

    As suspected, you will need to add the specific needed #using directives. BTW, the example you were talking about is at http://msdn2.microsoft.com/en-us/library/system.codedom.compiler.codedomprovider.aspx and the link does actually contain all the needed info.

    I needed to modify some of your code to be able to compile. Here is my version of your code:

    //Sample.cpp
    #using <mscorlib.dll>
    #using <System.Windows.Forms.dll>
    #using <System.Drawing.dll>
    #using <System.dll>
    #using <Microsoft.JScript.dll>
    #using <Cscompmgd.dll>

    using namespace System;
    using namespace System::CodeDom;
    using namespace System::CodeDom::Compiler;
    using namespace System::Collections;
    using namespace System::ComponentModel;
    using namespace System::Diagnostics;
    using namespace System::Drawing;
    using namespace System::IO;
    using namespace System::Windows::Forms;
    using namespace Microsoft::CSharp;
    using namespace Microsoft::VisualBasic;
    using namespace Microsoft::JScript;
    using namespace System::Security::Permissions;

    static bool CompileCode( CodeDomProvider^ provider, String^
                                          sourceFile, String^ exeFile )
    {
        // Obtain an ICodeCompiler from a CodeDomProvider class.
        ICodeCompiler^ compiler = provider->CreateCompiler();
        CompilerParameters^ cp = gcnew CompilerParameters;
        if ( ( !cp) || ( !compiler) )
        {
           return false;
        }
          // Generate an executable instead of a class library.
         cp->GenerateExecutable = true;
         // Set the assembly file name to generate.
         cp->OutputAssembly = exeFile;
         // Generate debug information.
         cp->IncludeDebugInformation = true;
         // Add an assembly reference.
         cp->ReferencedAssemblies->Add( "System.dll" );
         // Save the assembly as a physical file.
         cp->GenerateInMemory = false;
         // Set the warning level at which  the compiler should abort compilation if a warning of this level occurrs.
         cp->WarningLevel = 3;
         // Set whether to treat all warnings as errors.
         cp->TreatWarningsAsErrors = false;
         // Set compiler argument to optimize output.
         cp->CompilerOptions = "/optimize";
         // Set a temporary files collection.
         // The TempFileCollection stores the temporary files
         // generated during a build in the current directory,
         // and does not delete them after compilation.
         cp->TempFiles = gcnew TempFileCollection( ".",true );
         ICodeGenerator^ generator = provider->CreateGenerator();  
      if ( generator->Supports (GeneratorSupport::EntryPointMethod) )
         {
             // Specify the class that contains  the main method of the executable.
             cp->MainClass = "Samples.Class1";
          }
          if ( generator->Supports( GeneratorSupport::Resources ) )
          {
             // Set the embedded resource file of the assembly. This is  useful for culture-neutral resources, or default (fallback) resources.
             cp->EmbeddedResources->Add( "Default.resources" );
             // Set the linked resource reference files of the assembly.
            // These resources are included in separate assembly files,
             // typically localized for a specific language and culture.
             cp->LinkedResources->Add( "nb-no.resources" );
           }
           // Invoke compilation.
            CompilerResults^ cr = compiler->CompileAssemblyFromFile( cp, sourceFile );
           if ( cr->Errors->Count > 0 )
           {
              // Display compilation errors.
              Console::WriteLine( "Errors building {0} into {1}",
       sourceFile, cr->PathToAssembly );
        for each ( System::CodeDom::Compiler::CompilerError^ ce in cr->Errors )
                {
                   Console::WriteLine( " {0}", ce->ToString() ); 
                  Console::WriteLine();
                }
            }
           else
           {
               Console::WriteLine( "Source {0} built into {1} successfully.",sourceFile, cr->PathToAssembly );
            }
                 // Return the results of compilation.
            if ( cr->Errors->Count > 0 )
           {
               return false;
           }
           else
          {
               return true;
          }
    }
    int main()
    {
     return 0;
    }

    Through the command line, you just need to compile cl /CLR sample.cpp

    Through the IDE, create an empty CLR project and add sample.cpp and then just build the application.

    BTW, the best place for the errors you were seeing is actually the .net development forums at http://forums.microsoft.com/MSDN/default.aspx ForumGroupID=12&SiteID=1 since most of the classes you are using are .NET framwork ones.

    Thanks,
      Ayman Shoukry
      VC++ Team



  • cori

    Let me direct you attention that specially for C++, the forums can't really help you understand the whole language. Thse forums can only direct you or help you in specific issues. I would really recommend trial and error as well as reading books.

    Also, make sure to look spend some time reading the links provided in my previous post in case they can help address your issue.

    Post the specific issue and will probably look into it on Monday.


    Thanks,
      Ayman Shoukry
      VC++ Team



  • d.g.holm

    BTW, while working with CLR projects I could never open that reference window either. I recall it clearly.

  • Dennis Jackson

    I suspect I know what is going on here: is this file compiled with /Yu If it is then any code before the pre-compiled header file, stdafx.h in this case, is ignored.

    Try moving the namespace using directives after the #include statements.



  • CodeCanvas

    I am reading the latest Harry Potter and Half Blooded Prince now and I am at the stage where he got hold of a "luck potion." I must have drunk unluck potion unbeknown to me right before I started this project. Anyhow, you code does not compile belive it or not. Honestly I can hardly believe it myself, you must have compiled it, I am sure.

    I created a CLR C++ project via the following steps: File-->new-->project-->Other Languages-->C++-->CLR Console Application. Project named, a new file AymanSample.cpp created, your code put in. Attempts at compilation:

    (1) Build-->Compile-->Error: Error   1   fatal error C1010: unexpected end of file while looking for precompiled header. Did you forget to add '#include "stdafx.h"' to your source  

    Now, this file is in the project amongst "header files." Fine, I added a precompile directive #include <stdafx.h> to the source -- the same error.

    (2) View-->Other Windows-->Command Window-->cl /CLR AymanSample.cpp-->error: "Command 'cl' is not valid"

    (3) In desperation: DOS Command Prompt-->navigating to the project directory-->cl /CLR AymanSource.cpp-->warning:  unknown option /CLR; fatal error: C1021: invalid preprocessor command 'using'

    What am I doing wrong or what are you doing wrong

    Incidently, I got that code from a different place, I swear. It was coded as a main.

    When you said: "Command Line" did you mean "Command Window "

    Expecting your input.

    Thanks.



  • Ang Bain

    What if you do in the above example: #using <mscorlib.dll>, of course you will need to compile with /CLR in this case if you want to use such reference. Take a look at the following link: http://msdn2.microsoft.com/en-us/library/yab9swk4.aspx

    If you want to just have a native application (No CLR) then you need to create your dll and export the APIs there and then import such APIs from you application. Take a look at http://msdn2.microsoft.com/en-us/library/z4zxe9k8.aspx for more details.

    You have been asking questions in totally different directions. What do you want to actually do Could you post a COMPLETE STAND ALONE SAMPLE that reproduces the issue (AND ALL THE STEPS NEEDED FROM THE POINT WHEN YOU CREATED YOU PROJECT TO WHERE YOU PUT YOUR CODE). Without such samlpe, all what we can do is just to speculate what might be happening.

    With respect to you previous post stating:
    "What is going on guys Do you have anybody on your C++ team who can get more than C-- mark on their knowledge of the system you are supposed to chaperon Is MS getting its money's worth with you I do not think so. "

    Do you really think that this a good way of communicating with folks that are spending time here trying to help you I understand that you might be frustrated but I don't believe stating such comments would be the best way for communication. Any ways, I don't want to stop too long on such comment. If you have more details for reprodcuing the issue as described above, I will be more than happy to assign someone to investigate the issue.

    Thanks,
    Ayman Shoukry
    Program Manager
    VC++ Team





  • Michael J. Liu

    Thanks, I will formulate what I am trying to do more clearly and post as complete example as possible. I will start with a heuristic formulation. Then I will try to recreate my steps on the way here. You are right, I have been asking questions leading into many different directions but it is because all the approaches I tried so far haven't brought any result. I still do not quite understand if it is because of my inexperience with C++ (I have more experience with C# and some other OO languages) or because of lame support. It took me 2 weeks to grasp all intricacies of MS FoxPro9 because of the marvelous forum over there. Those guys are superb. SQL Server support groups are also very good.

    Give me two hours to phrase everything. By 12:00 EST I will be ready, perhaps even sooner.

    Sorry for my red font but I had to do something to attract your attention, guys.

    Thanks.

  • Jeff Putz

    The reason for these errors is that you are not referenceing the assemblies that actually define these namespaces and the types they contain.

    You need to reference mscorlib.dll (that defines System::String) and system.dll (that defines the CodeDomProvider).

    The reference an assembly you can either do via the command-line (using the /FU switch) or programmatically (using the #using directive).

  • vijayan n

    I need to tap a stream of datagrams coming into an application in my computer, actually three different applications. I have no idea how the data is formatted but may eventually find out via inquiries or my own investigation. At this stage I will be happy if I could tap the stream asynchroniously. I understand that there might be conceptual problems down the road like undeterministic distribution of the stream into one or another socket at the port. I discount this and other problems at this stage. All I want to do is to construct an application and experiment with it because I can trust only myself and my own experience.

    Ayman or somebody else told me before that my best bet would be unamanged code. It means CAsyncSocket class.

    I have had great difficulties following your instructions as to choosing various options for compiler /Zd, etc. since they all lead to various inconsistencies.

    In an attempt to bypass this bottleneck I set this file up to try to do the compilation programmatically without all the difficulties associated with the browser because it is so difficult to control all options in there. I get errors trying to compile this file. I copied the file from MSDN help but today I could not find the original even after spending close to an hour. The original was a main source file. What I did was to convert it to a function, nothing else. I added namespaces and #include statements after first crash at the compilation. I did it fairly haphazardly, rather in desperation.

    using
    namespace System;
    using namespace System::Object;
    using namespace System::CodeDom;
    using namespace System::Configuration;
    using namespace System::CodeDom::Compiler;
    using namespace System::CodeDom::Compiler::CodeDomProvider;
    using namespace System::String;
    using namespace System::Web::Compilation;
    using namespace System::Web::Configuration;
    using namespace System::Object::Microsoft::VisualC::CodeDomTypeInfo;

    #include <stdafx.h>
    #include <stdarg.h>
    #include "unknwn.h"
    #include <winternl.h>
    #include <windows.h>

    static bool CompileCode( CodeDomProvider^ provider, String^ 
                                          sourceFile, String^ exeFile )
    {
        // Obtain an ICodeCompiler from a CodeDomProvider class.
        ICodeCompiler^ compiler = provider->CreateCompiler();
        CompilerParameters^ cp =
    gcnew CompilerParameters;
        if ( ( !cp) || ( !compiler) )
        { 
          
    return false;
        }
          // Generate an executable instead of a class library.
         cp->GenerateExecutable = true;
         // Set the assembly file name to generate.
         cp->OutputAssembly = exeFile;
         // Generate debug information.
         cp->IncludeDebugInformation = true;
         // Add an assembly reference.
         cp->ReferencedAssemblies->Add( "System.dll" );
         // Save the assembly as a physical file.
         cp->GenerateInMemory = false;
         // Set the warning level at which  the compiler should abort compilation if a warning of this level occurrs.
         cp->WarningLevel = 3;
         // Set whether to treat all warnings as errors.
         cp->TreatWarningsAsErrors = false;
         // Set compiler argument to optimize output.
         cp->CompilerOptions = "/optimize";
         // Set a temporary files collection.
         // The TempFileCollection stores the temporary files
         // generated during a build in the current directory,
         // and does not delete them after compilation.
         cp->TempFiles = gcnew TempFileCollection( ".",true );
         ICodeGenerator^ generator = provider->CreateGenerator();
       
         if
    ( generator->Supports 
               GeneratorSupport::EntryPointMethod ) ) 
         {
             // Specify the class that contains  the main method of the executable.
             cp->MainClass = "Samples.Class1";
          }
          if ( generator->Supports( GeneratorSupport::Resources ) ) 
          {
             // Set the embedded resource file of the assembly. This is  useful for culture-neutral resources, or default (fallback) resources.
             cp->EmbeddedResources->Add( "Default.resources" );
             // Set the linked resource reference files of the assembly.
            // These resources are included in separate assembly files,
             // typically localized for a specific language and culture.
             cp->LinkedResources->Add( "nb-no.resources" );
           }
           // Invoke compilation.
            CompilerResults^ cr = compiler->CompileAssemblyFromFile( cp, sourceFile ); 
           if ( cr->Errors->Count > 0 ) 
           {
              // Display compilation errors.
              Console::WriteLine( "Errors building {0} into {1}",
       sourceFile, cr->PathToAssembly );
              for each ( CompilerError^ ce in cr->Errors )
                {
                   Console::WriteLine(
    " {0}", ce->ToString() );  
                  Console::WriteLine();
                }
            } 
           else
           {
               Console::WriteLine(
    "Source {0} built into {1} successfully.",sourceFile, cr->PathToAssembly );
            }
                 // Return the results of compilation.
            if ( cr->Errors->Count > 0 )
           {
               return false;
           }
           else
          {
               return true;
          }
    }

    These are the errors I am getting:
    Error 1 error C2065: 'CodeDomProvider' : undeclared identifier 
    Error 3 error C2065: 'String' : undeclared identifier 

    I do not understand why

    I need to pass at least one stage, this one, then I will discuss issues on the next level.

    I do not think I should copy the whole log file for you now but if you need it I will. Feel free to ask for any information. Also, please keep in mind that I want to solve THIS SPECIFIC PROBLEM first without any diversion. I want this file to COMPILE, period. I see no reason why it should not.

    Thanks in advance.



  • York Wu

    I actually tried it already. It results in many more fatal errors. Just as an example:

    Error 1 error C2871: 'System' : a namespace with this name does not exist 

    Also Object, CodeDom, Compiler, etc. are not recognized. I just reproduced it again.

    What is going on guys Do you have anybody on your C++ team who can get more than C-- mark on their knowledge of the system you are supposed to chaperon Is MS getting its money's worth with you I do not think so.

  • Thanh

    Thank you for the prompt answer. I am at the end of my rope tonight and about to call it quits. I will study your post tomorrow. I may still come back with more questions.

    Thanks.

  • MCastellana

    There is a problem here and if you can help me to resolve it I may stop bugging you so often.

    I cannot enter anything in the reference field, NOTHING.

    When I click on Project-->Properties-->Common Properties-->References-->Add New Reference I get a window that is WRITE-PROTECTED. I cannot enter anything in it. I want to know why

    On top of that, even it it was not write protected, the window is sort of meaningless in a weird way. There are two tabs on top of it: "Project Name" and "Project Directory." Why do I have to reference another project for my project I want to reference a .dll or .lib file, I presume. Is it not a reqasonable expectation

    I am waiting for your answer please.


  • Nitin Tarkar

    This mean that you don't have a CLR project. You should create a new project and this time ensure that you pick one of the project types under the CLR node in the tree.

  • Michel GUINTOLI

    I did have a CLR project but it ended up in so many problems which I do not precisely recall now that I was advised by Ayman to do a Console application without CLR with MFC support only. He could not help me resolve those issues. It looks I am getting run around all the time. I need unmanaged code by the virtue of my cAsyncSocket approach at least at this stage.

    Why can I not have a reference entered without CLR support

    I am tired and may be off for today but I will resume bugging you guys tomorrow, mind you.

  • setting compiler options programmatically.