Multiple files error when including already compiled symbols
Th following example will help reproduce the issue. This probably could be reduced to just the print_string.st file and the program.
------------------------------------------------------------File : main.cpp------------------------------------------------------------
#include <iostream>
using namespace std;
extern "C" {
// Declare a struct for the function block
typedef struct {
bool ci;
int printer;
char in[50];
} print_string;
// Declare a struct for the program
typedef struct {
print_string printstr;
} myprogram_struct;
// Declare the instance of the program as external
extern myprogram_struct myprogram_instance;
// Declare imported global variables as external
extern unsigned int gnExternalIf;
// Declare the external "public" method by using the program call signature
void myprogram(myprogram_struct*);
}
int main(int argc, char * argv[]){
gnExternalIf = 2;
myprogram(&myprogram_instance);
//std::cout << "Number is " << std::to_string(gnExternalIf) << std::endl;
return 0;
}
------------------------------------------------------------File : myprogram.st------------------------------------------------------------
program myprogram
var_temp
asign1 : dint ;
asign2 : dint ;
asign3 : dint ;
end_var
var
printstr : print_string;
myfb : myfunctionblock;
end_var
if gnExternalIf = 0 then
asign1 := gnExternalIf + 10;
asign2 := gnExternalIf + 20;
elsif gnExternalIf = 1 then
asign1 := gnExternalIf + 50;
asign2 := gnExternalIf + 60;
else
asign1 := gnExternalIf + 100;
asign2 := gnExternalIf + 110;
end_if;
myfb(inVariable1 := asign1, inVariable2 := asign2);
asign3 = myfb.outResult;
printstr( CI := TRUE,
PRINTER := asign3,
IN := ' : result');
end_program
------------------------------------------------------------File : myfunctionblock.st--------------------------------------------------------
FUNCTION_BLOCK myfunctionblock
(* External Interface *)
VAR_INPUT
(* Put your input variable declarations here *)
inVariable1 : dint ;
inVariable2 : dint ;
END_VAR
VAR_OUTPUT
(* Put your output variable declarations here *)
outResult : dint := 0;
END_VAR
(* Local Variables *)
VAR
(* Put your local variable declarations here *)
iTemp1 : dint ;
iTemp2 : dint ;
END_VAR
(* Function Block Body *)
iTemp1 := inVariable1 ;
iTemp2 := inVariable2 ;
outResult := myfunction(iTemp1, iTemp2);
gnExternalIf := 10;
END_FUNCTION_BLOCK
------------------------------------------------------------File : myfunction.st--------------------------------------------------------
FUNCTION myfunction : DINT
VAR_INPUT
iParam1 : DINT;
iParam2 : DINT;
END_VAR
VAR_TEMP
iResult : DINT := 0;
END_VAR
iResult := iParam1 * iParam2;
myfunction := iResult;
END_FUNCTION
------------------------------------------------------------File : print_string.st--------------------------------------------------------
{external}
FUNCTION puts : DINT
VAR_INPUT {ref}
text : STRING;
END_VAR
END_FUNCTION
{external}
FUNCTION printf : DINT
VAR_INPUT {ref}
format : STRING;
END_VAR
VAR_INPUT
args: ...;
END_VAR
END_FUNCTION
FUNCTION_BLOCK print_string
VAR_INPUT
CI : BOOL := TRUE ; (* Control in. *)
PRINTER : DINT := 1 ; (* Printer number *)
IN : STRING ; (* The value to print. *)
END_VAR
VAR_OUTPUT
CO : BOOL ; (* Control out. *)
END_VAR
printf('CI : %d, PRINTER : %d, IN : ', CI, PRINTER);
puts(IN);
END_FUNCTION_BLOCK
List of commands To Build Individual ST sources are mentioned below,
plc -c print_string.st -o print_string.o
plc -c myfunction.st -o myfunction.o
plc -i myfunction.st -i myglobalvars.st -c myfunctionblock.st -o myfunctionblock.o
plc -i print_string.st -i myglobalvars.st -i myfunctionblock.st -c myprogram.st -o myprogram.o
clang++ -c main.cpp -o main.o
clang++ main.o myprogram.o myfunctionblock.o print_string.o -o Test
Error Received During Compilation Are:
/usr/bin/ld: myfunctionblock.o:(.rodata+0x0): multiple definition of `__myfunctionblock__init'; myprogram.o:(.rodata+0x60): first defined here
/usr/bin/ld: print_string.o:(.rodata+0x0): multiple definition of `__print_string__init'; myprogram.o:(.rodata+0x0): first defined here
/usr/bin/ld: print_string.o: relocation R_X86_64_32 against `.rodata.str1.16' can not be used when making a PIE object; recompile with -fPIE
/usr/bin/ld: failed to set dynamic section sizes: bad value
Originally posted by @PBaswat in https://github.com/PLC-lang/rusty/discussions/1035
I think we could make the __init variables we use for initializers external when including a file. If the file ends up not being included/linked the linker will complain anyway