Author Topic: Generate .h/.cpp by scripting using advanced property  (Read 6118 times)

Offline Feneck91

  • Multiple posting newcomer
  • *
  • Posts: 112
Generate .h/.cpp by scripting using advanced property
« on: August 01, 2011, 04:54:30 pm »
Hello.

I'm trying to make library (wxETKSQLite3) over wxSQLite3 (wich use sqlite3 database engine) to create database structure with only database description.
The idea is to have a description file named "foo.ws3" for example that will contains a table description like:

Code
WX_ETK_SQLITE3_DECLARE_TABLE(TMatchType)
        COLUMN_PRIMARY_KEY_INTEGER(idTMatchType)
        COLUMN_TEXT_NOT_NULL_UNIQUE(Label)
        COLUMN_DOUBLE_NOT_NULL(Coeff)
        COLUMN_TEXT_NULL(Comments)

That generate a class wxETKSQLite3Table with all field, methods (derived from wxETKSQLite3Table), table description that will be compiled by the compiler.
I could run any command line on project files (properties on file / build (check compile file) / advanced (check use custom command to build this file)
My first idea is to install lua in command line and an lua script will be use to parse the ws3 file and generate both .h/.cpp file (that should be added on project).

Problem, to use it, you must install lua. Is it possible to use another (portable) scripting that codeblocks use ? like squirrel ? I know codeblocks use squirrel but I think it is only for plugin. Is it possibleto call some multi-platform scripting engine from this command line ?

It will be used, when all description will be done to make easy request/table binding with c++ code, database creation and request without typing any SQL request. I already made this kind of thing (at work) to remove (and so replace) Roguewave library.

Another problem are dependencies: the ws3 file must be "compile" before the 2 generated files.

Any idea ?

Another way is to use build script in project/target options / Attached build scripts ???????????????
« Last Edit: August 01, 2011, 05:36:10 pm by Feneck91 »

Offline Feneck91

  • Multiple posting newcomer
  • *
  • Posts: 112
Re: Generate .h/.cpp by scripting using advanced property
« Reply #1 on: August 01, 2011, 11:03:25 pm »
In project properties, build script (in project/target options) - Attached build scripts, I add my own "compile_ws3.script"

Code
// base is CompileTargetBase object
function SetBuildOptions(base)
{
    LogWarning(_T("---------------------------------------------"));
    LogWarning(_T("--           SetBuildOptions               --"));
    LogWarning(_T("---------------------------------------------"));

    local cbProject = GetProjectManager().IsOpen(base.GetFilename())
    if (cbProject != null)
    {
        local i = 0;
        for (i=0;i<cbProject.GetFilesCount();i++)
        {
            if (cbProject.GetFile(i).file.GetExt().Matches(_T("ws3")))
            {   // Generate match file
                GenerateWS3(cbProject.GetFile(i));
            }
        }
    }
}

function GenerateWS3(pProject)
{
    ShowError(pProject.file.GetFullPath(wxPATH_NATIVE));

    local wxFileNameCPP = ::wxFileName(); // Create new instance of wxFileName
    local wxFileNameH   = ::wxFileName(); // Create new instance of wxFileName

    // Create 2 file names: cpp and h files
    wxFileNameCPP.Assign(pProject.file.GetFullPath(wxPATH_NATIVE),wxPATH_NATIVE);
    wxFileNameH.Assign(pProject.file.GetFullPath(wxPATH_NATIVE),wxPATH_NATIVE);
    wxFileNameCPP.SetExt(EXT_CPP);
    wxFileNameH.SetExt(EXT_H);

    // Now, test if header / source code / wx3 files have same modification time
//    LogWarning(wxFileNameCPP.GetFullPath(wxPATH_NATIVE));

//    local wx
    //wxFileNameCPP.GetTimes(null,null,null);

    // *not work * if (wxFileNameCPP.GetModificationTime() != pProject.file.GetModificationTime())
    {
        ShowError(wxFileNameCPP.GetFullPath(wxPATH_NATIVE));
        ShowError(wxFileNameH.GetFullPath(wxPATH_NATIVE));
    }

    // After writting header + source code, modify each files modification date with same as WS3 file
    // *noy work * wxFileNameCPP.SetTimes(null,pProject.file.GetModificationTime(),null);
}

A lot of strange things. This script is called 3 times each time I compile. Certainly at the beginning of the build, then at pre/post build step.
But I don't know (in script) in case I am.
No documentation very explicit, I don't know what can I do .... but is seem really powerful !
Documentation :
http://wiki.codeblocks.org/index.php?title=Scripting_commands
http://wiki.codeblocks.org/index.php?title=Build_scripts

Somebody who do this developement into code::blocks can help me ?
Some other documentation ?

Offline Feneck91

  • Multiple posting newcomer
  • *
  • Posts: 112
Re: Generate .h/.cpp by scripting using advanced property
« Reply #2 on: August 02, 2011, 10:54:23 am »
I begin the script. Not sure it is a good idea (?) but using script to generate file is cool because script engine is embeded into Code::Block and so, is multi plateform.
Is it possible to add squirrel scripting to compile the file, and how to ? (custom command to build this file)
Is it possible to know in SetBuildOptions when this script is called ? (init / pre build post build) ? Have take a look at CompilerCommandGenerator class but don't found a way...

I show the squirrel code if it can be help...
Code
/**
 * Generate files source files from ws3 description.
 *
 * This script is called before the project/target is built, Each build script must define
 * this function, even if it is not needed (in which case you can leave it with an empty body).
 *
 * Help can be found here:
 *  - Base page:          http://wiki.codeblocks.org/index.php?title=Scripting_Code::Blocks
 *  - Scripting commands: http://wiki.codeblocks.org/index.php?title=Scripting_commands
 *  - Build scripts:      http://wiki.codeblocks.org/index.php?title=Build_scripts
 *
 * @param pCompileTargetBase CompileTargetBase instance.
 */
function SetBuildOptions(pCompileTargetBase)
{
//    LogWarning(_T("---------------------------------------------"));
//    LogWarning(_T("--           SetBuildOptions               --"));
//    LogWarning(_T("---------------------------------------------"));

    local cbProject = GetProjectManager().IsOpen(pCompileTargetBase.GetFilename())
    if (!IsNull(cbProject))
    {
        local i = 0;
        for (i=0;i<cbProject.GetFilesCount();i++)
        {//sq_tostring
            if (cbProject.GetFile(i).file.GetExt().tostring() == "ws3")
            {   // Generate match file
                GenerateWS3(cbProject,cbProject.GetFile(i));
            }
        }
    }
}

/**
 * Generate the header / source code from ws3 description file.
 *
 * @param pProject Project instance, it is the project where the ws3 was found.
 * @param pProjectFile ProjectFile instance of ws3 project file. It contains the ws3
 *                     file path to read and generate.
 */
function GenerateWS3(pProject,pProjectFile)
{
    local wxFileNameCPP = ::wxFileName(); // Create new instance of wxFileName
    local wxFileNameH   = ::wxFileName(); // Create new instance of wxFileName

    // Create 2 file names: cpp and h files
    wxFileNameCPP.Assign(pProjectFile.file.GetFullPath(wxPATH_NATIVE),wxPATH_NATIVE);
    wxFileNameH.Assign(pProjectFile.file.GetFullPath(wxPATH_NATIVE),wxPATH_NATIVE);
    wxFileNameCPP.SetExt(EXT_CPP);
    wxFileNameH.SetExt(EXT_H);

    AddToProjectIfNotExists(pProject,wxFileNameCPP);
    AddToProjectIfNotExists(pProject,wxFileNameH);
    //wxFileNameCPP.GetModificationTime();

    // Now, test if header / source code / wx3 files have same modification time
//    LogWarning(wxFileNameCPP.GetFullPath(wxPATH_NATIVE));

//    local wx
    //wxFileNameCPP.GetTimes(null,null,null);

    // *not work * if (wxFileNameCPP.GetModificationTime() != pProjectFile.file.GetModificationTime())
    {
        //ShowError(wxFileNameCPP.GetFullPath(wxPATH_NATIVE));
        //ShowError(wxFileNameH.GetFullPath(wxPATH_NATIVE));
    }

    // After writting header + source code, modify each files modification date with same as WS3 file
    // *noy work * wxFileNameCPP.SetTimes(null,pProjectFile.file.GetModificationTime(),null);
}

/**
 * Detect and add the header / source to project if they doesn't exists.
 *
 * @param pProject Project instance, it is the project where the ws3 was found.
 * @param pFileName wxFileName instance of file to verify/add to project.
 */
function AddToProjectIfNotExists(pProject,pFileName)
{
    local i = 0;
    local bFound = false;
    for (i=0;i<pProject.GetFilesCount();i++)
    {
        if (pProject.GetFile(i).file.GetFullPath(wxPATH_NATIVE).tostring() == pFileName.GetFullPath(wxPATH_NATIVE).tostring())
        {   // Don't add the pFileName file
            bFound = true;
            break;
        }
    }
    if (!bFound)
    {   //-----------------------------------------------------------------------------------
        // AddFile(targetIndex,filename,compile, link,weight): Add a file to the project.
        // @param targetIndex The index of the build target to add this file to.
        // @param filename The file's filename. This *must* be a filename relative to the project's path.
        // @param compile If true this file is compiled when building the project.
        // @param link If true this file is linked when building the project.
        // @param weight A value between zero and 100 (defaults to 50). Smaller weight, makes the file compile earlier than those with larger weight.
        // @return The newly added file or NULL if something went wrong.
        //-----------------------------------------------------------------------------------
        local bCompileAndLink = true;
        if (pFileName.GetExt().tostring() == EXT_H.tostring())
        {
            bCompileAndLink = false;
        }
        // Add the file for all project targets
        local iTargetIndex;
        local pProjectFile = null; // Instance of ProjectFile
        for (iTargetIndex=0;iTargetIndex<pProject.GetBuildTargetsCount();iTargetIndex++)
        {
            if (IsNull(pProjectFile))
            {   // Add the file to the first target
                pProjectFile = pProject.AddFile(iTargetIndex,pFileName.GetFullPath(wxPATH_NATIVE),bCompileAndLink,bCompileAndLink,50);
                if (IsNull(pProjectFile))
                {   // Error, failed to add file
                    break;
                }
                else
                {
                    Log(_T("Added file '") + pFileName.GetFullPath(wxPATH_NATIVE) + _T("'"));
                    Log(_T("  Added Build Target = '") + pProject.GetBuildTarget(iTargetIndex).GetFullTitle() + _T("'"));
                }
            }
            else
            {   // Add all target to this
                pProjectFile.AddBuildTarget(pProject.GetBuildTarget(iTargetIndex).GetTitle());
                Log(_T("  Added Build Target = '") + pProject.GetBuildTarget(iTargetIndex).GetFullTitle() + _T("'"));
            }
        }

        if (IsNull(pProjectFile))
        {
            Log(_T("Failed on added file '") + pFileName.GetFullPath(wxPATH_NATIVE) + _T("'"));
        }
        else
        {   // Log and save to let the workspace to load and display the changes
            Log(_T("Added file '") + pFileName.GetFullPath(wxPATH_NATIVE));
            pProject.SetModified(true);
            GetProjectManager().SaveProject(pProject);
        }
    }
}

Offline Freem

  • Almost regular
  • **
  • Posts: 219
Re: Generate .h/.cpp by scripting using advanced property
« Reply #3 on: August 02, 2011, 08:39:11 pm »
I will try to understand the problem, but I'm sorry, I'm a bit confused.

In fact, you would like something like Qt do with it's signals? (I mean, pre-compiling files to generate pure C++ files)
And want to make a generic project to use your lib?
So I would say that you should say to the wizard to make your script running in pre-build.

Then, make the compiling by calling yourself the command line of the compilation for ws3 files (but I'm not sure if you have any mean to learn the name of used compiler)
To know at which moment you are running, why don't test the presence of files in a C::B's standard directory, like "obj/debug" (I said this as an example)? If there is nothing, you can't be in pre-build mode. (but if there is something you could be in pre-build, this is problematic... maybe if you can look "last modified date" ?)

But I think the easier would be to add the generated files to C::B's, giving them a higher priority in compilation? The question is, is it possible...

I'm not sure to have really understood your problem and the point you are on the way to success... (I'm more sure that I'm very far to help you, to be honest...)
And, I don't know the scripting engine of C::B's, so I'm sorry to have probably bothered you...

Offline Feneck91

  • Multiple posting newcomer
  • *
  • Posts: 112
Re: Generate .h/.cpp by scripting using advanced property
« Reply #4 on: August 02, 2011, 09:17:18 pm »
I'm software engineer for 15 years old, and I done often some special build into Visual C++. These custom build can make lot of things: make a software is not only build C/C++ file. For example, it can generate dll language by running external tools (that use dictionnary ... MFC don't use gettext !!), or running crypting tools to be used with dongle.
I often use external software (exe) or running vbscript with parameters to make special build (you can do lot of things with vbscript, look here at the bottom of the page.
Here, I want make a library to easilly create sqlite tables and create request ... but I don't want it make more work than if I don't use my own lib (that is not written for the moment, I think it will be make me lot of time).
Idea ? Transform : 
Quote
WX_ETK_SQLITE3_DECLARE_TABLE(TMatchType)
{
    DECLARE_COLUMN    idTMatchType  INTEGER     PRIMARY_KEY
    DECLARE_COLUMN  Label           TEXT        NOT_NULL        UNIQUE
    DECLARE_COLUMN  Coeff           DOUBLE      NOT_NULL
    DECLARE_COLUMN  Comments        TEXT
}
to :
Code
class TTGestLibTableTMatchType : public wxETKSQLite3Table
{
public:
    static wxETKSQLite3Column   idTMatchType;
    static wxETKSQLite3Column   Label;
    static wxETKSQLite3Column   Coeff;
    static wxETKSQLite3Column   Comments;

public:
    /**
     * Default constructor.
     */
    TTGestLibTableTMatchType();

    /**
     * Default destructor.
     */
    virtual ~TTGestLibTableTMatchType();
};
Code
#include "TTGestLibDatabaseStructure.h"

wxETKSQLite3Column TTGestLibTableTMatchType::idTMatchType(_T("idTMatchType"),WXSQLITE_INTEGER,true,true,true,false);
wxETKSQLite3Column TTGestLibTableTMatchType::Label(_T("Label"),WXSQLITE_TEXT,false,true,false,false);
wxETKSQLite3Column TTGestLibTableTMatchType::Coeff(_T("Coeff"),WXSQLITE_FLOAT,false,false,false,false);
wxETKSQLite3Column TTGestLibTableTMatchType::Comments(_T("Comments"),WXSQLITE_TEXT,false,false,false,true);

TTGestLibTableTMatchType::TTGestLibTableTMatchType()
    : wxETKSQLite3Table(_T("TMatchType"))
{
    AddColumn(idTMatchType;
    AddColumn(Label);
    AddColumn(Coeff);
    AddColumn(Comments);
}

I can create an exe to make the transformation, it is possible, but must be build before building the lib, usinf script embedded with Code::Blocks make this script multi-platform.
Quote
maybe if you can look "last modified date" ?
For the moment it seems to be not possible with squirrel.
Code
But I think the easier would be to add the generated files to C::B's, giving them a higher priority in compilation? The question is, is it possible...
There are 100 priority when adding file to Code::Blocks (I saw it into the codeblocks source code), default is 50, but it can be add only with scripting.
Quote
Then, make the compiling by calling yourself the command line of the compilation for ws3 files
I would to call command line that run squirrel scripting, it will be fantastic but I think it is not possible.

Thanks for your reply, hope other peaple will help me.

Offline Freem

  • Almost regular
  • **
  • Posts: 219
Re: Generate .h/.cpp by scripting using advanced property
« Reply #5 on: August 02, 2011, 10:04:59 pm »
15 years... well I don't think I can help... only a bit more than a year in a professional environment. And it was a year  alone, using all knowledge I'd learned by myself, not really sufficient to make a project valid from A to Z...

I know that the highest priority is 100, but without looking sources.
But I don't understand what you mean by "but it can be add only with scripting."? Do you mean that you can't change priority by script?

Quote
I would to call command line that run squirrel scripting, it will be fantastic but I think it is not possible.
There is nothing to allow you to access toolchains executables?
I remember something else, about C::B. I'd read somewhere (in this forum I guess, or the wiki) that it generate a custom makefile, then execute is (well, make it, to be more precise) and last, remove it. This read was saying it was possible to avoid the last step or removing... I can't say more, and I'm not sure about that. I'm  not a C::B'sguru...

As you see, I can just ask things... with the hope my question will trigger some idea...

Offline Feneck91

  • Multiple posting newcomer
  • *
  • Posts: 112
Re: Generate .h/.cpp by scripting using advanced property
« Reply #6 on: August 02, 2011, 11:48:13 pm »
15 years... well I don't think I can help... only a bit more than a year in a professional environment. And it was a year  alone, using all knowledge I'd learned by myself, not really sufficient to make a project valid from A to Z...

I know that the highest priority is 100, but without looking sources.
But I don't understand what you mean by "but it can be add only with scripting."? Do you mean that you can't change priority by script?
I see in code codeblocks\src\include\cbproject.h
Function: ProjectFile* AddFile(AddFile(int targetIndex, const wxString& filename, bool compile = true, bool link = true, unsigned short int weight = 50);
Code
        // AddFile(targetIndex,filename,compile, link,weight): Add a file to the project.
        // @param targetIndex The index of the build target to add this file to.
        // @param filename The file's filename. This *must* be a filename relative to the project's path.
        // @param compile If true this file is compiled when building the project.
        // @param link If true this file is linked when building the project.
        // @param weight A value between zero and 100 (defaults to 50). Smaller weight, makes the file compile earlier than those with larger weight.
        // @return The newly added file or NULL if something went wrong.
I never seen in File property / Build : priority weight !! Yes, it is existing...

There is nothing to allow you to access toolchains executables?
I remember something else, about C::B. I'd read somewhere (in this forum I guess, or the wiki) that it generate a custom makefile, then execute is (well, make it, to be more precise) and last, remove it. This read was saying it was possible to avoid the last step or removing... I can't say more, and I'm not sure about that. I'm  not a C::B'sguru...
As you see, I can just ask things... with the hope my question will trigger some idea...
Toolchains executables are use for compiler.... I want to script this work, It should be integrated into Code::Blocks.
Or may be modifying source code of Code::Blocks, I have already do this by added part of Alatar stacked base tab switching (mouse limitation, Code::Blocks properties and add check in environment settings see here)

I post here because I want a Code::Blocks guru's HELP ME !!  :D