Переглянути джерело

Fixed dynamic Beef libs on Linux/macOS

Brian Fiete 5 роки тому
батько
коміт
6e5b6694a1

+ 2 - 0
BeefRT/CMakeLists.txt

@@ -16,6 +16,8 @@ set(OUTPUT_RELEASE Release/bin)
 
 project(${PROJECT_NAME} CXX C)
 
+add_compile_options(-fPIC)
+
 # Define Release by default.
 if(NOT CMAKE_BUILD_TYPE)
   set(CMAKE_BUILD_TYPE "Debug")

+ 27 - 13
BeefySysLib/platform/posix/PosixCommon.cpp

@@ -304,9 +304,21 @@ void mkdir(const char* path)
 
 typedef void(*CrashInfoFunc)();
 
-static CritSect gSysCritSect;
-static String gCrashInfo;
-static Array<CrashInfoFunc> gCrashInfoFuncs;
+struct BfpGlobalData
+{
+	CritSect mSysCritSect;
+	String mCrashInfo;
+	Array<CrashInfoFunc> mCrashInfoFuncs;
+};
+
+static BfpGlobalData* gBfpGlobal;
+
+static BfpGlobalData* BfpGetGlobalData()
+{
+	if (gBfpGlobal == NULL)
+		gBfpGlobal = new BfpGlobalData();
+	return gBfpGlobal;
+}
 
 #ifdef BFP_HAS_BACKTRACE
 
@@ -437,18 +449,18 @@ static void Crashed()
 {
     //
     {
-        AutoCrit autoCrit(gSysCritSect);
+        AutoCrit autoCrit(BfpGetGlobalData()->mSysCritSect);
 
         String debugDump;
 
         debugDump += "**** FATAL APPLICATION ERROR ****\n";
 
-        for (auto func : gCrashInfoFuncs)
+        for (auto func : BfpGetGlobalData()->mCrashInfoFuncs)
             func();
 
-        if (!gCrashInfo.IsEmpty())
+        if (!BfpGetGlobalData()->mCrashInfo.IsEmpty())
         {
-            debugDump += gCrashInfo;
+            debugDump += BfpGetGlobalData()->mCrashInfo;
             debugDump += "\n";
         }
 
@@ -498,14 +510,16 @@ static void SigHandler(int sig)
     }
 
     if (sigName != NULL)
-        gCrashInfo += StrFormat("Signal: %s\n", sigName);
+		BfpGetGlobalData()->mCrashInfo += StrFormat("Signal: %s\n", sigName);
     else
-        gCrashInfo += StrFormat("Signal: %d\n", sig);
+		BfpGetGlobalData()->mCrashInfo += StrFormat("Signal: %d\n", sig);
     Crashed();
 }
 
 BFP_EXPORT void BFP_CALLTYPE BfpSystem_Init(int version, BfpSystemInitFlags flags)
 {
+	BfpGetGlobalData();
+
     if (version != BFP_VERSION)
     {
         BfpSystem_FatalError(StrFormat("Bfp build version '%d' does not match requested version '%d'", BFP_VERSION, version).c_str(), "BFP FATAL ERROR");
@@ -561,14 +575,14 @@ BFP_EXPORT void BFP_CALLTYPE BfpSystem_SetCrashReportKind(BfpCrashReportKind cra
 
 BFP_EXPORT void BFP_CALLTYPE BfpSystem_AddCrashInfoFunc(BfpCrashInfoFunc crashInfoFunc)
 {
-    AutoCrit autoCrit(gSysCritSect);
-    gCrashInfoFuncs.Add(crashInfoFunc);
+    AutoCrit autoCrit(BfpGetGlobalData()->mSysCritSect);
+	BfpGetGlobalData()->mCrashInfoFuncs.Add(crashInfoFunc);
 }
 
 BFP_EXPORT void BFP_CALLTYPE BfpSystem_AddCrashInfo(const char* str) // Can do at any time, or during CrashInfoFunc callbacks
 {
-    AutoCrit autoCrit(gSysCritSect);
-    gCrashInfo.Append(str);
+    AutoCrit autoCrit(BfpGetGlobalData()->mSysCritSect);
+	BfpGetGlobalData()->mCrashInfo.Append(str);
 }
 
 void BfpSystem_Shutdown()

+ 10 - 5
IDE/src/BuildContext.bf

@@ -313,7 +313,9 @@ namespace IDE
 				testProjectInfo = gApp.mTestManager.GetProjectInfo(project);
 
 			bool isExe = (project.mGeneralOptions.mTargetType != Project.TargetType.BeefLib) || (testProjectInfo != null);
-			if (isExe)
+			bool isDynLib = project.mGeneralOptions.mTargetType == Project.TargetType.BeefDynLib;
+
+			if (isExe || isDynLib)
 			{
 				CopyLibFiles(targetPath, workspaceOptions, options);
 
@@ -335,6 +337,11 @@ namespace IDE
 					linkLine.Append(" ");
 			    }*/
 
+				if (isDynLib)
+				{
+					linkLine.Append("-shared ");
+				}
+
 				if ((mPlatformType == .Windows) &&
 			    	((project.mGeneralOptions.mTargetType == Project.TargetType.BeefGUIApplication) ||
 			        (project.mGeneralOptions.mTargetType == Project.TargetType.C_GUIApplication)))
@@ -1092,10 +1099,8 @@ namespace IDE
 				absOutputDir.Append(projectBuildDir);
 				outputDir = absOutputDir;
 				targetPath.Append(outputDir, "/", project.mProjectName);
-#if BF_PLATFORM_WINDOWS
-				targetPath.Append(".exe");
-#endif
-
+				if (mPlatformType == .Windows)
+					targetPath.Append(".exe");
 				Debug.Assert(testProjectInfo.mTestExePath == null);
 				testProjectInfo.mTestExePath = new String(targetPath);
 			}

+ 13 - 3
IDE/src/IDEApp.bf

@@ -8337,6 +8337,8 @@ namespace IDE
 
             bfProject.SetDisabled(false);
 
+			let platform = Workspace.PlatformType.GetFromName(mPlatformName);
+
             var preprocessorMacros = scope DefinesSet();
 			void AddMacros(List<String> macros)
 			{
@@ -8406,10 +8408,18 @@ namespace IDE
 				}
 			}
 
+			var relocType = options.mBeefOptions.mRelocType;
+
+			if (relocType == .NotSet)
+			{
+				if (platform != .Windows)
+					relocType = .PIC;
+			}
+
             bfProject.SetOptions(targetType,
                 project.mBeefGlobalOptions.mStartupObject,
                 preprocessorMacros.mDefines,
-                optimizationLevel, ltoType, options.mBeefOptions.mRelocType, options.mBeefOptions.mPICLevel,
+                optimizationLevel, ltoType, relocType, options.mBeefOptions.mPICLevel,
 				options.mBeefOptions.mMergeFunctions, options.mBeefOptions.mCombineLoads,
                 options.mBeefOptions.mVectorizeLoops, options.mBeefOptions.mVectorizeSLP);
 
@@ -8930,10 +8940,10 @@ namespace IDE
 											else if (project.mGeneralOptions.mTargetType != .CustomBuild)
 											    newString.Append(".exe");
 										case .macOS:
-											if (project.mGeneralOptions.mTargetType == Project.TargetType.BeefLib)
+											if (project.mGeneralOptions.mTargetType == .BeefLib)
 												newString.Append(".dylib");
 										default:
-											if (project.mGeneralOptions.mTargetType == Project.TargetType.BeefLib)
+											if (project.mGeneralOptions.mTargetType == .BeefDynLib)
 												newString.Append(".so");
 										}
 									}

+ 6 - 0
IDEHelper/Backend/BeIRCodeGen.cpp

@@ -2318,6 +2318,12 @@ void BeIRCodeGen::HandleNextCmd()
 				else if (attribute == BFIRAttribute_NoRecurse)
 				{
 				}
+				else if (attribute == BFIRAttribute_Constructor)
+				{
+				}
+				else if (attribute == BFIRAttribute_Destructor)
+				{
+				}
 				else
 					BF_FATAL("Unhandled");
 			}			

+ 36 - 3
IDEHelper/Compiler/BfCompiler.cpp

@@ -735,7 +735,7 @@ BfIRFunction BfCompiler::CreateLoadSharedLibraries(BfVDataModule* bfModule, Arra
 							bfModule->GetDefaultValue(bfModule->GetPrimitiveType(BfTypeCode_NullPtr)), dllHandleName);
 
 						BfIRValue namePtr = bfModule->GetStringCharPtr(strNum);
-						SmallVector<BfIRValue, 1> args;
+						SmallVector<BfIRValue, 2> args;
 						args.push_back(namePtr);
 						args.push_back(dllHandleVar);
 						BfIRValue dllHandleValue = bfModule->mBfIRBuilder->CreateCall(loadSharedLibraryProc.mFunc, args);
@@ -1624,6 +1624,8 @@ void BfCompiler::CreateVData(BfVDataModule* bfModule)
 	if ((targetType == BfTargetType_BeefWindowsApplication) && (mOptions.mPlatformType != BfPlatformType_Windows))
 		targetType = BfTargetType_BeefConsoleApplication;
 
+	bool isPosixDynLib = (targetType == BfTargetType_BeefDynLib) && (mOptions.mPlatformType != BfPlatformType_Windows);
+	
 	// Generate "main"
 	if (!IsHotCompile())
 	{
@@ -1677,7 +1679,8 @@ void BfCompiler::CreateVData(BfVDataModule* bfModule)
 		auto entryBlock = bfModule->mBfIRBuilder->CreateBlock("entry", true);
 		bfModule->mBfIRBuilder->SetInsertPoint(entryBlock);
 		
-#ifndef BF_PLATFORM_WINDOWS
+		if ((mOptions.mPlatformType != BfPlatformType_Windows) && 
+			((targetType == BfTargetType_BeefConsoleApplication) || (targetType == BfTargetType_BeefTest)))
         {
             SmallVector<BfIRType, 2> paramTypes;
             paramTypes.push_back(int32Type);
@@ -1692,7 +1695,6 @@ void BfCompiler::CreateVData(BfVDataModule* bfModule)
             args.push_back(bfModule->mBfIRBuilder->GetArgument(1));
             bfModule->mBfIRBuilder->CreateCall(setCmdLineFunc, args);
         }
-#endif
 		
 		BfIRBlock initSkipBlock;
 		if (targetType == BfTargetType_BeefDynLib)
@@ -1949,6 +1951,37 @@ void BfCompiler::CreateVData(BfVDataModule* bfModule)
 			BfIRMDNode dbgArrayType = bfModule->mBfIRBuilder->DbgCreateArrayType(dataSize * 8, 8, bfModule->mBfIRBuilder->DbgGetType(int8Type), dataSize);
 			bfModule->mBfIRBuilder->DbgCreateGlobalVariable(bfModule->mDICompileUnit, name, name, NULL, 0, dbgArrayType, false, irVal);
 		}
+
+		if (isPosixDynLib)
+		{
+			auto voidType = bfModule->mBfIRBuilder->MapType(bfModule->GetPrimitiveType(BfTypeCode_None));
+			SizedArray<BfIRType, 4> paramTypes;
+			BfIRFunctionType funcType = bfModule->mBfIRBuilder->CreateFunctionType(voidType, paramTypes);
+			BfIRFunction func = bfModule->mBfIRBuilder->CreateFunction(funcType, BfIRLinkageType_Internal, "BfDynLib__Startup");
+			bfModule->mBfIRBuilder->SetActiveFunction(func);
+			bfModule->mBfIRBuilder->Func_AddAttribute(func, -1, BFIRAttribute_Constructor);
+			auto entryBlock = bfModule->mBfIRBuilder->CreateBlock("main", true);
+			bfModule->mBfIRBuilder->SetInsertPoint(entryBlock);
+
+			SmallVector<BfIRValue, 2> startArgs;
+			startArgs.push_back(bfModule->mBfIRBuilder->CreateConstNull());
+			startArgs.push_back(bfModule->mBfIRBuilder->CreateConst(BfTypeCode_Int32, 1));
+			startArgs.push_back(bfModule->mBfIRBuilder->CreateConstNull());
+			bfModule->mBfIRBuilder->CreateCall(mainFunc, startArgs);
+			bfModule->mBfIRBuilder->CreateRetVoid();			
+
+			//////////////////////////////////////////////////////////////////////////
+									
+			func = bfModule->mBfIRBuilder->CreateFunction(funcType, BfIRLinkageType_Internal, "BfDynLib__Shutdown");
+			bfModule->mBfIRBuilder->Func_AddAttribute(func, -1, BFIRAttribute_Destructor);
+			bfModule->mBfIRBuilder->SetActiveFunction(func);
+			entryBlock = bfModule->mBfIRBuilder->CreateBlock("main", true);
+			bfModule->mBfIRBuilder->SetInsertPoint(entryBlock);
+			SmallVector<BfIRValue, 2> stopArgs;			
+			startArgs[1] = bfModule->mBfIRBuilder->CreateConst(BfTypeCode_Int32, 0);
+			bfModule->mBfIRBuilder->CreateCall(mainFunc, startArgs);
+			bfModule->mBfIRBuilder->CreateRetVoid();
+		}
 	}
 	
 	// Generate "System.GC.MarkAllStaticMembers"	

+ 3 - 1
IDEHelper/Compiler/BfIRBuilder.h

@@ -611,7 +611,9 @@ enum BfIRAttribute
 	BFIRAttribute_NoFramePointerElim,
 	BFIRAttribute_DllImport,
 	BFIRAttribute_DllExport,
-	BFIRAttribute_NoRecurse
+	BFIRAttribute_NoRecurse,
+	BFIRAttribute_Constructor,
+	BFIRAttribute_Destructor,
 };
 
 struct BfIRFunctionType

+ 29 - 0
IDEHelper/Compiler/BfIRCodeGen.cpp

@@ -2737,6 +2737,35 @@ void BfIRCodeGen::HandleNextCmd()
 			{
 				func->addFnAttr("no-frame-pointer-elim", "true");
 			}
+			else if ((attribute == BFIRAttribute_Constructor) || (attribute == BFIRAttribute_Destructor))
+			{
+				CmdParamVec<llvm::Type*> members;
+				members.push_back(llvm::Type::getInt32Ty(*mLLVMContext));
+				members.push_back(func->getType());
+				members.push_back(llvm::Type::getInt8PtrTy(*mLLVMContext));
+				llvm::StructType* structType = llvm::StructType::get(*mLLVMContext, members);
+
+				CmdParamVec<llvm::Constant*> structVals;
+				structVals.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(*mLLVMContext), 0x7FFFFF00));
+				structVals.push_back(func);
+				structVals.push_back(llvm::ConstantPointerNull::get(llvm::Type::getInt8PtrTy(*mLLVMContext)));				
+				auto constStruct = llvm::ConstantStruct::get(structType, structVals);
+				
+				CmdParamVec<llvm::Constant*> structArrVals;
+				structArrVals.push_back(constStruct);
+
+				auto arrTy = llvm::ArrayType::get(structType, 1);
+				auto constArr = llvm::ConstantArray::get(arrTy, structArrVals);
+
+				auto globalVariable = new llvm::GlobalVariable(
+					*mLLVMModule,
+					arrTy,
+					false,
+					llvm::GlobalValue::AppendingLinkage,
+					constArr,
+					(attribute == BFIRAttribute_Constructor) ? "llvm.global_ctors" : "llvm.global_dtors",
+					NULL, llvm::GlobalValue::NotThreadLocal);								
+			}			
 			else
 				func->addAttribute(argIdx, LLVMMapAttribute(attribute));
 		}

+ 6 - 1
IDEHelper/Compiler/BfMangler.cpp

@@ -719,7 +719,12 @@ String BfGNUMangler::Mangle(BfMethodInstance* methodInst)
 	}
 	
 	mangleContext.mPrefixObjectPointer = true;
-	String methodName = methodInst->mMethodDef->mName;
+	StringT<128> methodName = methodInst->mMethodDef->mName;
+	for (int i = 0; i < (int)methodName.length(); i++)
+	{
+		if (methodName[i] == '@')
+			methodName[i] = '$';
+	}
 
 	if (methodInst->mMethodDef->mIsOperator)
 	{

+ 7 - 8
bin/build.sh

@@ -3,6 +3,7 @@ echo Starting build.sh
 
 PATH=/usr/local/bin:$PATH:$HOME/bin
 SCRIPTPATH=$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)
+ROOTPATH="$(dirname "$SCRIPTPATH")"
 echo Building from from $SCRIPTPATH
 cd $SCRIPTPATH
 
@@ -50,15 +51,13 @@ else
 	LINKOPTS="-ldl -lpthread -Wl,-rpath -Wl,\$ORIGIN"
 fi
 
-if [ ! -L libBeefRT_d.a ]; then	
-	ln -s ../../jbuild_d/Debug/bin/libBeefRT_d.a libBeefRT_d.a
-	ln -s ../../jbuild_d/Debug/bin/libBeefySysLib_d.$LIBEXT libBeefySysLib_d.$LIBEXT
-	ln -s ../../jbuild_d/Debug/bin/libIDEHelper_d.$LIBEXT libIDEHelper_d.$LIBEXT
+ln -s -f $ROOTPATH/jbuild_d/Debug/bin/libBeefRT_d.a libBeefRT_d.a
+ln -s -f $ROOTPATH/jbuild_d/Debug/bin/libBeefySysLib_d.$LIBEXT libBeefySysLib_d.$LIBEXT
+ln -s -f $ROOTPATH/jbuild_d/Debug/bin/libIDEHelper_d.$LIBEXT libIDEHelper_d.$LIBEXT
 
-	ln -s ../../jbuild/Release/bin/libBeefRT.a libBeefRT.a
-	ln -s ../../jbuild/Release/bin/libBeefySysLib.$LIBEXT libBeefySysLib.$LIBEXT
-	ln -s ../../jbuild/Release/bin/libIDEHelper.$LIBEXT libIDEHelper.$LIBEXT
-fi
+ln -s -f $ROOTPATH/jbuild/Release/bin/libBeefRT.a libBeefRT.a
+ln -s -f $ROOTPATH/jbuild/Release/bin/libBeefySysLib.$LIBEXT libBeefySysLib.$LIBEXT
+ln -s -f $ROOTPATH/jbuild/Release/bin/libIDEHelper.$LIBEXT libIDEHelper.$LIBEXT
 
 ### DEBUG ###