Menu

#933 #INCLUDE ONCE not working for starting-module/file (bug or undocumented feature?)

open
nobody
None
compiler
2021-04-15
2021-02-22
No

I'm using the meta-command #INCLUDE verry often to get a good structure of my tools during programming with freebasic. And I'm using a lot of self-made-code to test my tools.
The structure got more and more complex and it started to get more and more errors during compiling and they made me wondering, because this errors were not the reason of my problems!

I've found out, that if I start my coding with v.e. main.bas and I take v.e. 2 module-files I named them sub1.bas and sub2.bas and if I include (for some reason) in one of the included files like:

#INCLUDE ONCE main.bas

... I get the error:

main.bas(9) error 4: Duplicated definition, foo in 'Dim foo As String'

that is, because main.bas is executed 2 times !
1st time at start
2nd time at #INCLUDE ONCE main.bas (please look to sub2.bas)

Solution could be: the starting-file should be put on the list of included files as well at start to avoid the 2nd use of that code.

Thank You for help.

main.bas

#Print Compiling the module main.bas
'
' main.bas
'
#Include Once "C:\Program Files\freeBASIC\freeBASIC\sub1.bas"
#Include Once "C:\Program Files\freeBASIC\freeBASIC\sub2.bas"
'
'
Dim foo As String
'
Print "test done"
Sleep 3000
'
'

sub1.bas

'
#Print Compiling the module sub1.bas
'
' sub1.bas
'
#Include Once "C:\Program Files\freeBASIC\freeBASIC\sub1.bas"
#Include Once "C:\Program Files\freeBASIC\freeBASIC\sub2.bas"
'
'
Print "sub1 done"
'

sub2.bas

'
#Print Compiling the module sub2.bas
'
' sub2.bas
'
#Include Once "C:\Program Files\freeBASIC\freeBASIC\sub1.bas"
#Include Once "C:\Program Files\freeBASIC\freeBASIC\sub2.bas"
'
'          v-------- this "Once" is NOT working correct for the 1st top main-program main.bas
#Include Once "C:\Program Files\freeBASIC\freeBASIC\main.bas"
'
Print "sub2 done" 
'

result:
without the line {#Include Once "main.bas"} at file sub2.bas

sub2 done
sub1 done
test done

compile-log:

C:\Program Files\freeBASIC\freeBASIC\fbc -s gui -showincludes "main.bas"
main.bas
Compiling the module main.bas
 |  sub1.bas
Compiling the module sub1.bas
 |   |  (sub1.bas)
 |   |  sub2.bas
Compiling the module sub2.bas
 |   |   |  (sub1.bas)
 |   |   |  (sub2.bas)
 |   |   |  main.bas
Compiling the main.bas
 |   |   |   |  (sub1.bas)
 |   |   |   |  (sub2.bas)
 |  (sub2.bas)
main.bas(9) error 4: Duplicated definition, foo in 'Dim foo As String'

Build error(s)

Discussion

  • fxm (freebasic.net)

    The Once specifier tells the compiler to include the file only once even if it is included several times by the source code.

    In your example the expression '#Include Once "C:\Program Files\freeBASIC\freeBASIC\sub1.bas"' is encountered multiple times so only one include expression is kept.
    Likewise for 'sub2.bas'.

    But for 'main.bas', a single expression '#Include Once "C:\Program Files\freeBASIC\freeBASIC\main.bas"' is encountered, so it is kept, which explains the double declaration of 'foo'.

     
    • LordMaserati

      LordMaserati - 2021-02-22

      thank You for that fast answer ...
      but what You'r explaining are facts that are known and I know.
      My exaples are only a short explanation of the problem.

      Did You understood the problem?
      I dont know how to call the first file. Start-code-file, "grand-grand-grand....-father"-file or the "first"-file which ist the begin of whole code.
      This start-file should be put on the list of included file by compiler. To be sure, in which case ever, never be included a 2nd time! Otherwise a lot of implementations have same troubles whith this inconsistency (I think a lot of problems at forum are caused by this, because error-message are verry confusing)

       
  • LordMaserati

    LordMaserati - 2021-02-22

    ...

     

    Last edit: LordMaserati 2021-02-22
  • Jeff Marshall

    Jeff Marshall - 2021-04-15

    One easy thing you can do help keep organized with the structure of your program is to:
    - use a .bas filename extension for files that get compiled (the files listed on the fbc command line)
    - use a .bi filename extension for files that get included.
    Maybe have a look at:
    -Source Files
    -Header Files

    Here's some really simple example programs to highlight the current behaviours of #include once and #pragma once.

    PROGRAM 1 (#include once):

    E:\fb\fbc-bugs\933>type 933-include-once.bas 
    '' filename: 933-include-once.bas 
    #print __FILE__
    #include once "933-include-once.bas"
    

    Relative Path:

    E:\fb\fbc-bugs\933>fbc 933-include-once.bas 
    933-include-once.bas
    E:\fb\fbc-bugs\933\933-include-once.bas
    

    Absolute Path:

    E:\fb\fbc-bugs\933>fbc e:\fb\fbc-bugs\933\933-include-once.bas  
    e:\fb\fbc-bugs\933\933-include-once.bas
    e:\fb\fbc-bugs\933\933-include-once.bas
    

    PROGRAM 2 (#pragma once, #include):

    E:\fb\fbc-bugs\933>type 933-pragma-once.bas 
    '' filename: 933-pragma-once.bas
    #pragma once
    #print __FILE__
    #include "933-pragma-once.bas"
    

    Relative Path:

    E:\fb\fbc-bugs\933>fbc 933-pragma-once.bas 
    933-pragma-once.bas
    E:\fb\fbc-bugs\933\933-pragma-once.bas
    

    Absolute Path:

    E:\fb\fbc-bugs\933>fbc e:\fb\fbc-bugs\933\933-pragma-once.bas 
    e:\fb\fbc-bugs\933\933-pragma-once.bas
    

    From the examples can see that we get slightly different behaviour between on #pragma once depending on if a relative or absolute path was used.

    I would expect the same behaviour for #pragma once in either case. And I suspect that fixing the #pragma once bug should fix the #include once bug. But I also suspect that will have to follow the filename usage through fbc. There's many places where fbc uses the relative filename only and to have fbc solve the relative path with an absolute path up front is going to change a lot of output that fbc generates.

    It's probably OK to have fbc have all files on the command line automatically be added as #include once files. I think it would be an unusual case for a main.bas level source file to include itself, however that could also be a tricky way to have the compiler make exactly a second pass only a source file; maybe first pass to set-up some #defines and a second pass to generate code. But that seems far fetched. But if that was the behaviour, then at least #pragma once should be made to work consistently

     

Log in to post a comment.