rusty icon indicating copy to clipboard operation
rusty copied to clipboard

Multiple files error when including already compiled symbols

Open ghaith opened this issue 2 years ago • 1 comments

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
Capture

Originally posted by @PBaswat in https://github.com/PLC-lang/rusty/discussions/1035

ghaith avatar Nov 29 '23 05:11 ghaith

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

ghaith avatar Dec 01 '23 06:12 ghaith